Skip to content

Commit

Permalink
overwork comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
Kr0nox committed Jul 27, 2023
1 parent 7a443d1 commit 96e153f
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import de.jplag.JPlagResult;
import de.jplag.Submission;
import de.jplag.Token;
import de.jplag.options.SimilarityMetric;
import de.jplag.reporting.FilePathUtil;
import de.jplag.reporting.reportobject.model.ComparisonReport;
import de.jplag.reporting.reportobject.model.Match;
Expand Down Expand Up @@ -55,7 +56,8 @@ private void writeComparisons(String path, List<JPlagComparison> comparisons) {
String secondSubmissionId = submissionToIdFunction.apply(comparison.secondSubmission());
String fileName = generateComparisonName(firstSubmissionId, secondSubmissionId);
addToLookUp(firstSubmissionId, secondSubmissionId, fileName);
var comparisonReport = new ComparisonReport(firstSubmissionId, secondSubmissionId, comparison.similarity(),
var comparisonReport = new ComparisonReport(firstSubmissionId, secondSubmissionId,
Map.of(SimilarityMetric.AVG.name(), comparison.similarity(), SimilarityMetric.MAX.name(), comparison.maximalSimilarity()),
convertMatchesToReportMatches(comparison));
fileWriter.saveAsJSON(comparisonReport, path, fileName);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package de.jplag.reporting.reportobject.model;

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
* ReportViewer DTO for the comparison of two submissions.
* @param firstSubmissionId id of the first submission
* @param secondSubmissionId id of the second submission
* @param similarity average similarity. between 0.0 and 1.0.
* @param similarities map of metric names and corresponding similarities. between 0.0 and 1.0.
* @param matches the list of matches found in the comparison of the two submissions
*/
public record ComparisonReport(@JsonProperty("id1") String firstSubmissionId, @JsonProperty("id2") String secondSubmissionId,
@JsonProperty("similarity") double similarity, @JsonProperty("matches") List<Match> matches) {
@JsonProperty("similarities") Map<String, Double> similarities, @JsonProperty("matches") List<Match> matches) {

}
103 changes: 25 additions & 78 deletions report-viewer/src/model/Comparison.ts
Original file line number Diff line number Diff line change
@@ -1,129 +1,76 @@
import type { Match } from './Match'
import type { SubmissionFile } from './SubmissionFile'
import type { MatchInSingleFile } from './MatchInSingleFile'
import type MetricType from './MetricType'

/**
* Comparison model used by the ComparisonView
*/
export class Comparison {
private readonly _firstSubmissionId: string
private readonly _secondSubmissionId: string
private readonly _similarity: number
private readonly _similarities: Record<MetricType, number>
private _filesOfFirstSubmission: Map<string, SubmissionFile>
private _filesOfSecondSubmission: Map<string, SubmissionFile>
private _allMatches: Array<Match>
private _matchesInFirstSubmission: Map<string, Array<MatchInSingleFile>>
private _matchesInSecondSubmissions: Map<string, Array<MatchInSingleFile>>

constructor(firstSubmissionId: string, secondSubmissionId: string, similarity: number) {
constructor(
firstSubmissionId: string,
secondSubmissionId: string,
similarities: Record<MetricType, number>,
filesOfFirstSubmission: Map<string, SubmissionFile>,
filesOfSecondSubmission: Map<string, SubmissionFile>,
allMatches: Array<Match>,
matchesInFirstSubmission: Map<string, Array<MatchInSingleFile>>,
matchesInSecondSubmissions: Map<string, Array<MatchInSingleFile>>
) {
this._firstSubmissionId = firstSubmissionId
this._secondSubmissionId = secondSubmissionId
this._similarity = similarity
this._filesOfFirstSubmission = new Map()
this._filesOfSecondSubmission = new Map()
this._colors = []
this._allMatches = []
this._matchesInFirstSubmission = new Map()
this._matchesInSecondSubmissions = new Map()
this._similarities = similarities
this._filesOfFirstSubmission = filesOfFirstSubmission
this._filesOfSecondSubmission = filesOfSecondSubmission
this._allMatches = allMatches
this._matchesInFirstSubmission = matchesInFirstSubmission
this._matchesInSecondSubmissions = matchesInSecondSubmissions
}

private _filesOfFirstSubmission: Map<string, SubmissionFile>

/**
* @return Map of all files of the first submission
*/
get filesOfFirstSubmission(): Map<string, SubmissionFile> {
return this._filesOfFirstSubmission
}

/**
* Set the files of the first submission
* @param value Map to set to
*/
set filesOfFirstSubmission(value: Map<string, SubmissionFile>) {
this._filesOfFirstSubmission = value
}

private _filesOfSecondSubmission: Map<string, SubmissionFile>

/**
* @return Map of all files of the second submission
*/
get filesOfSecondSubmission(): Map<string, SubmissionFile> {
return this._filesOfSecondSubmission
}

/**
* Set the files of the second submission
* @param value Map to set to
*/
set filesOfSecondSubmission(value: Map<string, SubmissionFile>) {
this._filesOfSecondSubmission = value
}

private _colors: Array<string>

/**
* @return Array of all colors used to display the matches
*/
get colors(): Array<string> {
return this._colors
}

/**
* Set the colors used to display the matches
* @param value Colors to set to
*/
set colors(value: Array<string>) {
this._colors = value
}

private _allMatches: Array<Match>

/**
* @return Array of all matches
*/
get allMatches(): Array<Match> {
return this._allMatches
}

/**
* Set the array of all matches
* @param value Matches to set to
*/
set allMatches(value: Array<Match>) {
this._allMatches = value
}

private _matchesInFirstSubmission: Map<string, Array<MatchInSingleFile>>

/**
* @return Map of all matches in the first submission
*/
get matchesInFirstSubmission(): Map<string, Array<MatchInSingleFile>> {
return this._matchesInFirstSubmission
}

/**
* Set the matches in the first submission
* @param value Matches in the first submission to set to
*/
set matchesInFirstSubmission(value: Map<string, Array<MatchInSingleFile>>) {
this._matchesInFirstSubmission = value
}

private _matchesInSecondSubmissions: Map<string, Array<MatchInSingleFile>>

/**
* @return Map of all matches in the second submission
*/
get matchesInSecondSubmissions(): Map<string, Array<MatchInSingleFile>> {
return this._matchesInSecondSubmissions
}

/**
* Set the matches in the second submission
* @param value Matches in the first submission to set to
*/
set matchesInSecondSubmissions(value: Map<string, Array<MatchInSingleFile>>) {
this._matchesInSecondSubmissions = value
}

/**
* @return Id of the first submission
*/
Expand All @@ -141,7 +88,7 @@ export class Comparison {
/**
* @return Similarity of the two submissions
*/
get similarity() {
return this._similarity
get similarities() {
return this._similarities
}
}
46 changes: 36 additions & 10 deletions report-viewer/src/model/factories/ComparisonFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import store from '@/stores/store'
import { generateColors } from '@/utils/ColorUtils'
import slash from 'slash'
import { BaseFactory } from './BaseFactory'
import MetricType from '../MetricType'

/**
* Factory class for creating Comparison objects
Expand Down Expand Up @@ -45,19 +46,44 @@ export class ComparisonFactory extends BaseFactory {
const colors = generateColors(matches.length, matchSaturation, matchLightness, matchAlpha)
const coloredMatches = matches.map((match, index) => this.mapMatch(match, colors[index]))

const comparison = new Comparison(
return new Comparison(
firstSubmissionId,
secondSubmissionId,
json.similarity as number
this.extractSimilarities(json),
filesOfFirstConverted,
filesOfSecondConverted,
coloredMatches,
this.groupMatchesByFileName(coloredMatches, 1),
this.groupMatchesByFileName(coloredMatches, 2)
)
comparison.filesOfFirstSubmission = filesOfFirstConverted
comparison.filesOfSecondSubmission = filesOfSecondConverted
comparison.colors = colors
comparison.allMatches = coloredMatches
comparison.matchesInFirstSubmission = this.groupMatchesByFileName(coloredMatches, 1)
comparison.matchesInSecondSubmissions = this.groupMatchesByFileName(coloredMatches, 2)

return comparison
}

private static extractSimilarities(json: Record<string, unknown>): Record<MetricType, number> {
if (json.similarities) {
return this.extractSimilaritiesFromMap(json.similarities as Record<string, number>)
} else if (json.similarity) {
return this.extractSimilaritiesFromSingleValue(json.similarity as number)
}
throw new Error('No similarities found in comparison file')
}

private static extractSimilaritiesFromSingleValue(
avgSimilarity: number
): Record<MetricType, number> {
return {
[MetricType.AVERAGE]: avgSimilarity,
[MetricType.MAXIMUM]: Number.NaN
}
}

private static extractSimilaritiesFromMap(
similarityMap: Record<string, number>
): Record<MetricType, number> {
const similarities = {} as Record<MetricType, number>
for (const [key, value] of Object.entries(similarityMap)) {
similarities[key as MetricType] = value
}
return similarities
}

private static convertToSubmissionFileList(
Expand Down
3 changes: 2 additions & 1 deletion report-viewer/src/views/ComparisonView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</h2>
<div class="flex flex-row">
<TextInformation label="Average Similarity"
>{{ (comparison.similarity * 100).toFixed(2) }}%</TextInformation
>{{ (comparison.similarities[MetricType.AVERAGE] * 100).toFixed(2) }}%</TextInformation
>
</div>
<MatchList
Expand Down Expand Up @@ -77,6 +77,7 @@ import Container from '@/components/ContainerComponent.vue'
import hljsLightMode from 'highlight.js/styles/vs.css?raw'
import hljsDarkMode from 'highlight.js/styles/vs2015.css?raw'
import router from '@/router'
import MetricType from '@/model/MetricType'
const props = defineProps({
firstId: {
Expand Down
74 changes: 74 additions & 0 deletions report-viewer/tests/unit/model/factories/ComparisonFactory.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { vi, it, beforeAll, describe, expect } from 'vitest'
import validNew from './ValidNewComparison.json'
import validOld from './ValidOldComparison.json'
import { ComparisonFactory } from '@/model/factories/ComparisonFactory'
import store from '@/stores/store'
import MetricType from '@/model/MetricType'

const store = {
state: {
localModeUsed: false,
zipModeUsed: true,
singleModeUsed: false,
files: {}
},
getComparisonFileName: (id1: string, id2: string) => {
return `${id1}-${id2}.json`
},
filesOfSubmission: (name: string) => {
return [
{
name: `${name}/Structure.java`,
value: ''
},
{
name: `${name}/Submission.java`,
value: ''
}
]
}
}

describe('Test JSON to Comparison', () => {
beforeAll(() => {
vi.mock('@/stores/store', () => ({
default: vi.fn(() => {
return store
})
}))
})

it('Post 5.0', () => {
store.state.files['root1-root2.json'] = JSON.stringify(validNew)

const result = ComparisonFactory.getComparison('root1', 'root2')

expect(result).toBeDefined()
expect(result.firstSubmissionId).toBe('root1')
expect(result.secondSubmissionId).toBe('root2')
expect(result.similarities[MetricType.AVERAGE]).toBe(0.6900452488687783)
expect(result.similarities[MetricType.MAXIMUM]).toBe(0.9936000000000001)
expect(result.filesOfFirstSubmission).toBeDefined()
expect(result.filesOfSecondSubmission).toBeDefined()
expect(result.allMatches.length).toBe(4)
expect(result.matchesInFirstSubmission.size).toBe(2)
expect(result.matchesInSecondSubmissions.size).toBe(2)
})

it('Pre 5.0', () => {
store.state.files['root1-root2.json'] = JSON.stringify(validOld)

const result = ComparisonFactory.getComparison('root1', 'root2')

expect(result).toBeDefined()
expect(result.firstSubmissionId).toBe('root1')
expect(result.secondSubmissionId).toBe('root2')
expect(result.similarities[MetricType.AVERAGE]).toBe(0.6900452488687783)
expect(result.similarities[MetricType.MAXIMUM]).toBe(Number.NaN)
expect(result.filesOfFirstSubmission).toBeDefined()
expect(result.filesOfSecondSubmission).toBeDefined()
expect(result.allMatches.length).toBe(4)
expect(result.matchesInFirstSubmission.size).toBe(2)
expect(result.matchesInSecondSubmissions.size).toBe(2)
})
})
Loading

0 comments on commit 96e153f

Please sign in to comment.