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

Draft: Optimize report viewer dto size #507

Closed
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion jplag/src/main/java/de/jplag/JPlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public JPlagResult run() throws ExitException {
JPlagResult result = comparisonStrategy.compareSubmissions(submissionSet);
errorCollector.print("\nTotal time for comparing submissions: " + TimeUtil.formatDuration(result.getDuration()), null);

result.setClusteringResult(ClusteringFactory.getClusterings(result.getComparisons(), options.getClusteringOptions()));
result.setClusteringResult(ClusteringFactory.getClusterings(result.getAllComparisons(), options.getClusteringOptions()));

return result;
}
Expand Down
36 changes: 27 additions & 9 deletions jplag/src/main/java/de/jplag/JPlagResult.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package de.jplag;

import java.util.List;
import java.util.function.Function;

import de.jplag.clustering.ClusteringResult;
import de.jplag.options.JPlagOptions;
import de.jplag.options.SimilarityMetric;

/**
* Encapsulates the results of a comparison of a set of source code submissions.
Expand All @@ -21,6 +23,7 @@ public class JPlagResult {
private final int[] similarityDistribution; // 10-element array representing the similarity distribution of the detected matches.

private List<ClusteringResult<Submission>> clusteringResult;
private final int SIMILARITY_DISTRIBUTION_SIZE = 10;

public JPlagResult(List<JPlagComparison> comparisons, SubmissionSet submissions, long durationInMillis, JPlagOptions options) {
this.comparisons = comparisons;
Expand All @@ -47,7 +50,7 @@ public void setClusteringResult(List<ClusteringResult<Submission>> clustering) {
/**
* @return a list of all comparisons sorted by percentage (descending)
*/
public List<JPlagComparison> getComparisons() {
public List<JPlagComparison> getAllComparisons() {
return comparisons;
}

Expand Down Expand Up @@ -93,34 +96,49 @@ public JPlagOptions getOptions() {
}

/**
* Returns the similarity distribution of detected matches in a 10-element array. Each entry represents the absolute
* frequency of matches whose similarity lies within the respective interval. Intervals: 0: [0% - 10%), 1: [10% - 20%),
* 2: [20% - 30%), ..., 9: [90% - 100%]
* For the {@link SimilarityMetric} JPlag was run with, this returns the similarity distribution of detected matches in
* a 10-element array. Each entry represents the absolute frequency of matches whose similarity lies within the
* respective interval. Intervals: 0: [0% - 10%), 1: [10% - 20%), 2: [20% - 30%), ..., 9: [90% - 100%]
* @return the similarity distribution array.
*/
public int[] getSimilarityDistribution() {
return similarityDistribution;
}

/**
* For the {@link SimilarityMetric#MAX} that is built in to every {@link JPlagComparison}, this returns the similarity
* distribution of detected matches in a 10-element array. Each entry represents the absolute frequency of matches whose
* similarity lies within the respective interval. Intervals: 0: [0% - 10%), 1: [10% - 20%), 2: [20% - 30%), ..., 9:
* [90% - 100%]
* @return the similarity distribution array. When JPlag was run with the {@link SimilarityMetric#MAX}, this will return
* the same distribution as {@link JPlagResult#getSimilarityDistribution()}
*/
public int[] getMaxSimilarityDistribution() {
return calculateDistributionFor(comparisons, (JPlagComparison::maximalSimilarity));
}

public List<ClusteringResult<Submission>> getClusteringResult() {
return this.clusteringResult;
}

@Override
public String toString() {
return String.format("JPlagResult { comparisons: %d, duration: %d ms, language: %s, submissions: %d }", getComparisons().size(),
return String.format("JPlagResult { comparisons: %d, duration: %d ms, language: %s, submissions: %d }", getAllComparisons().size(),
getDuration(), getOptions().getLanguageOption(), submissions.numberOfSubmissions());
}

/**
* Note: Before, comparisons with a similarity below the given threshold were also included in the similarity matrix.
*/
private int[] calculateSimilarityDistribution(List<JPlagComparison> comparisons) {
int[] similarityDistribution = new int[10];

comparisons.stream().map(JPlagComparison::similarity).map(percent -> percent / 10).map(Float::intValue).map(index -> index == 10 ? 9 : index)
.forEach(index -> similarityDistribution[index]++);
return calculateDistributionFor(comparisons, (JPlagComparison::similarity));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return calculateDistributionFor(comparisons, (JPlagComparison::similarity));
return calculateDistributionFor(comparisons, JPlagComparison::similarity);

}

private int[] calculateDistributionFor(List<JPlagComparison> comparisons, Function<JPlagComparison, Float> similarityExtractor) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make this lambda to a 'normal' loop. From my point of view, it's not that easy to read

int[] similarityDistribution = new int[SIMILARITY_DISTRIBUTION_SIZE];
comparisons.stream().map(similarityExtractor).map(percent -> percent / SIMILARITY_DISTRIBUTION_SIZE).map(Float::intValue)
.map(index -> index == SIMILARITY_DISTRIBUTION_SIZE ? SIMILARITY_DISTRIBUTION_SIZE - 1 : index)
.forEach(index -> similarityDistribution[SIMILARITY_DISTRIBUTION_SIZE - 1 - index]++);
return similarityDistribution;
}
}
13 changes: 2 additions & 11 deletions jplag/src/main/java/de/jplag/reporting/JsonReport.java
Original file line number Diff line number Diff line change
@@ -1,36 +1,27 @@
package de.jplag.reporting;

import java.io.File;
import java.util.List;

import de.jplag.JPlagResult;
import de.jplag.reporting.jsonfactory.JsonFactory;
import de.jplag.reporting.reportobject.ReportObjectFactory;
import de.jplag.reporting.reportobject.model.JPlagReport;

// ReportImplementation -> JsonReport

/**
* A report generator which reports the JPlagResult in Json format.
*/
public class JsonReport implements Report {

@Override
public List<String> getReportStrings(JPlagResult result) {
JPlagReport report = ReportObjectFactory.getReportObject(result);
return JsonFactory.getJsonStrings(report);
}

@Override
public boolean saveReport(JPlagResult result, String path) {
public void saveReport(JPlagResult result, String path) {
JPlagReport report = ReportObjectFactory.getReportObject(result);
File directory = new File(path);
if (!directory.exists()) {
if (!directory.mkdirs()) {
logger.error("Failed to create dir.");
}
}
return JsonFactory.saveJsonFiles(report, path);
JsonFactory.saveJsonFiles(report, path);
}

}
15 changes: 1 addition & 14 deletions jplag/src/main/java/de/jplag/reporting/Report.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
package de.jplag.reporting;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.jplag.JPlagResult;

// ReportStrategy -> Report

/**
* Strategy interface for reporting. A report generator should implement this interface.
*/
public interface Report {

Logger logger = LoggerFactory.getLogger(Report.class);

/**
* This function returns a list containing the report objects as simple strings. The first element is the string of the
* overview object. Each following element is a string of a comparison report object.
* @param result The result of a JPlag comparison
* @return A list containing report objects to string. First element is Overview. Other elements are comparisons.
*/
List<String> getReportStrings(JPlagResult result);

/**
* Creates and saves JPlag report files to the disk.
* @param result The result of a JPlag comparison.
* @param path Path to the directory where the report should be saved.
* @return True if the process is successful, otherwise false.
*/
boolean saveReport(JPlagResult result, String path);
void saveReport(JPlagResult result, String path);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import de.jplag.reporting.reportobject.model.ComparisonReport;
Expand All @@ -21,42 +18,20 @@ public class JsonFactory {

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

private static final ObjectMapper mapper = new ObjectMapper();

/**
* Uses Jackson to create Json Strings from JPlagReport object.
* @return A list, first element is Json String of Overview object. The rest elements are Json Strings of Comparison
* objects.
*/
public static List<String> getJsonStrings(JPlagReport jPlagReport) {
List<String> jsonReports = new ArrayList<>();
try {
jsonReports.add(mapper.writeValueAsString(jPlagReport.getOverviewReport()));
for (ComparisonReport comparisonReport : jPlagReport.getComparisons()) {
jsonReports.add(mapper.writeValueAsString(comparisonReport));
}
} catch (JsonProcessingException e) {
logger.error("Error converting object to json " + e.getMessage());
}
return jsonReports;
}

/**
* Creates Json Files for the given JPlagReport and saves them in the given folder.
* @return A boolean, representing whether the process was successful.
*/
public static boolean saveJsonFiles(JPlagReport jPlagReport, String folderPath) {
public static void saveJsonFiles(JPlagReport jPlagReport, String folderPath) {
try {
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(Path.of(folderPath, "overview.json").toFile(), jPlagReport.getOverviewReport());
for (ComparisonReport report : jPlagReport.getComparisons()) {
String name = report.getFirstSubmissionId().concat("-").concat(report.getSecondSubmissionId()).concat(".json");
mapper.writeValue(Path.of(folderPath, "overview.json").toFile(), jPlagReport.overviewReport());
mapper.writeValue(Path.of(folderPath, "lookUpTable.json").toFile(), jPlagReport.lineLookUpTable());
for (ComparisonReport report : jPlagReport.comparisons()) {
String name = report.firstSubmissionId().concat("-").concat(report.secondSubmissionId()).concat(".json");
mapper.writeValue(Path.of(folderPath, name).toFile(), report);
}
} catch (IOException e) {
logger.error("Failed to save json files: " + e.getMessage(), e);
return false;
}
return true;
}
}
Loading