From 34fa03b74e278f0080cd53112bee00035a198a95 Mon Sep 17 00:00:00 2001 From: Alex | Kronox Date: Mon, 11 Sep 2023 16:19:17 +0200 Subject: [PATCH 1/7] new color generation --- report-viewer/src/model/Match.ts | 6 +- .../src/model/factories/ComparisonFactory.ts | 55 +++++++++++++++---- report-viewer/src/utils/ColorUtils.ts | 12 +++- 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/report-viewer/src/model/Match.ts b/report-viewer/src/model/Match.ts index 43df6d1e2..21a597af0 100644 --- a/report-viewer/src/model/Match.ts +++ b/report-viewer/src/model/Match.ts @@ -7,9 +7,9 @@ * @property startInSecond - Starting line of the match in the second file. * @property endInSecond - Ending line of the match in the second file. * @property tokens - Number of tokens in the match. - * @property color - Color of the match. + * @property colorIndex - Index of the color to use for the match. */ -export type Match = { +export interface Match { firstFile: string secondFile: string startInFirst: number @@ -17,5 +17,5 @@ export type Match = { startInSecond: number endInSecond: number tokens: number - color: string + colorIndex?: number } diff --git a/report-viewer/src/model/factories/ComparisonFactory.ts b/report-viewer/src/model/factories/ComparisonFactory.ts index 19a1cd4e1..5b4f4dffe 100644 --- a/report-viewer/src/model/factories/ComparisonFactory.ts +++ b/report-viewer/src/model/factories/ComparisonFactory.ts @@ -1,7 +1,7 @@ import { Comparison } from '../Comparison' import type { Match } from '../Match' import { store } from '@/stores/store' -import { generateColors } from '@/utils/ColorUtils' +import { getMatchColorCount } from '@/utils/ColorUtils' import slash from 'slash' import { BaseFactory } from './BaseFactory' import { MetricType } from '../MetricType' @@ -36,11 +36,7 @@ export class ComparisonFactory extends BaseFactory { const matches = json.matches as Array> - const matchSaturation = 0.8 - const matchLightness = 0.5 - const matchAlpha = 0.3 - const colors = generateColors(matches.length, matchSaturation, matchLightness, matchAlpha) - const coloredMatches = matches.map((match, index) => this.mapMatch(match, colors[index])) + const unColredMatches = matches.map((match) => this.getMatch(match)) return new Comparison( firstSubmissionId, @@ -48,7 +44,7 @@ export class ComparisonFactory extends BaseFactory { this.extractSimilarities(json), filesOfFirstSubmission, filesOfSecondSubmission, - coloredMatches + this.colorMatches(unColredMatches) ) } @@ -102,7 +98,7 @@ export class ComparisonFactory extends BaseFactory { } } - private static mapMatch(match: Record, color: string): Match { + private static getMatch(match: Record): Match { return { firstFile: slash(match.file1 as string), secondFile: slash(match.file2 as string), @@ -110,8 +106,47 @@ export class ComparisonFactory extends BaseFactory { endInFirst: match.end1 as number, startInSecond: match.start2 as number, endInSecond: match.end2 as number, - tokens: match.tokens as number, - color: color + tokens: match.tokens as number } } + + private static colorMatches(matches: Match[]): Match[] { + const maxColorCount = getMatchColorCount() + let currentColorIndex = 0 + const matchesFirst = Array.from(matches) + .sort((a, b) => a.startInFirst - b.startInFirst) + .sort((a, b) => (a.firstFile > b.firstFile ? 1 : -1)) + const matchesSecond = Array.from(matches) + .sort((a, b) => a.startInSecond - b.startInSecond) + .sort((a, b) => (a.secondFile > b.secondFile ? 1 : -1)) + const sortedSize = Array.from(matches).sort((a, b) => a.tokens - b.tokens) + + function canColor(matchList: Match[], index: number) { + return ( + (index === 0 || matchList[index - 1].colorIndex !== currentColorIndex) && + (index === matchList.length - 1 || matchList[index + 1].colorIndex !== currentColorIndex) + ) + } + + for (let i = 0; i < matches.length; i++) { + const firstIndex = matchesFirst.findIndex((match) => match === matches[i]) + const secondIndex = matchesSecond.findIndex((match) => match === matches[i]) + const sortedIndex = sortedSize.findIndex((match) => match === matches[i]) + const startCounter = currentColorIndex + while ( + !canColor(matchesFirst, firstIndex) || + !canColor(matchesSecond, secondIndex) || + !canColor(sortedSize, sortedIndex) + ) { + currentColorIndex = (currentColorIndex + 1) % maxColorCount + + if (currentColorIndex == startCounter) { + throw 'No solution' + } + } + matches[i].colorIndex = currentColorIndex + currentColorIndex = (currentColorIndex + 1) % maxColorCount + } + return sortedSize + } } diff --git a/report-viewer/src/utils/ColorUtils.ts b/report-viewer/src/utils/ColorUtils.ts index e44adec27..770730f66 100644 --- a/report-viewer/src/utils/ColorUtils.ts +++ b/report-viewer/src/utils/ColorUtils.ts @@ -59,6 +59,16 @@ function generateColorsForInterval( return colors } +const matchColors: { red: number; green: number; blue: number }[] = [] + +function getMatchColorCount() { + return matchColors.length +} + +function getMatchColor(index: number, alpha: number) { + return `rgba(${matchColors[index].red}, ${matchColors[index].green}, ${matchColors[index].blue}, ${alpha})` +} + const graphColors = { ticksAndFont: computed(() => { return store().uiState.useDarkMode ? '#ffffff' : '#000000' @@ -71,4 +81,4 @@ const graphColors = { pointFill: 'rgba(190, 22, 34, 1)' } -export { generateColors, graphColors } +export { generateColors, graphColors, getMatchColorCount, getMatchColor } From 675599379055eb68fd4450ce0aee2fc21df6b910 Mon Sep 17 00:00:00 2001 From: Alex | Kronox Date: Mon, 11 Sep 2023 16:57:20 +0200 Subject: [PATCH 2/7] implement colors --- report-viewer/src/components/CodePanel.vue | 6 +++++- report-viewer/src/components/MatchList.vue | 3 ++- report-viewer/src/model/factories/ComparisonFactory.ts | 2 +- report-viewer/src/utils/ColorUtils.ts | 10 +++++++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/report-viewer/src/components/CodePanel.vue b/report-viewer/src/components/CodePanel.vue index c057ae5a6..6dacf9852 100644 --- a/report-viewer/src/components/CodePanel.vue +++ b/report-viewer/src/components/CodePanel.vue @@ -28,7 +28,10 @@

@@ -52,6 +55,7 @@ import type { Match } from '@/model/Match'
 import type { SubmissionFile } from '@/stores/state'
 import { highlight } from '@/utils/CodeHighlighter'
 import type { HighlightLanguage } from '@/model/Language'
+import { getMatchColor } from '@/utils/ColorUtils'
 
 const props = defineProps({
   /**
diff --git a/report-viewer/src/components/MatchList.vue b/report-viewer/src/components/MatchList.vue
index aeb218112..3a1e5f66d 100644
--- a/report-viewer/src/components/MatchList.vue
+++ b/report-viewer/src/components/MatchList.vue
@@ -9,7 +9,7 @@
     
import type { Match } from '@/model/Match' import Interactable from './InteractableComponent.vue' +import { getMatchColor } from '@/utils/ColorUtils' defineProps({ /** diff --git a/report-viewer/src/model/factories/ComparisonFactory.ts b/report-viewer/src/model/factories/ComparisonFactory.ts index 5b4f4dffe..e6f3bd1cd 100644 --- a/report-viewer/src/model/factories/ComparisonFactory.ts +++ b/report-viewer/src/model/factories/ComparisonFactory.ts @@ -119,7 +119,7 @@ export class ComparisonFactory extends BaseFactory { const matchesSecond = Array.from(matches) .sort((a, b) => a.startInSecond - b.startInSecond) .sort((a, b) => (a.secondFile > b.secondFile ? 1 : -1)) - const sortedSize = Array.from(matches).sort((a, b) => a.tokens - b.tokens) + const sortedSize = Array.from(matches).sort((a, b) => b.tokens - a.tokens) function canColor(matchList: Match[], index: number) { return ( diff --git a/report-viewer/src/utils/ColorUtils.ts b/report-viewer/src/utils/ColorUtils.ts index 770730f66..53184c9f9 100644 --- a/report-viewer/src/utils/ColorUtils.ts +++ b/report-viewer/src/utils/ColorUtils.ts @@ -59,7 +59,15 @@ function generateColorsForInterval( return colors } -const matchColors: { red: number; green: number; blue: number }[] = [] +const matchColors: { red: number; green: number; blue: number }[] = [ + { red: 0, green: 9, blue: 255 }, + { red: 254, green: 255, blue: 0 }, + { red: 0, green: 255, blue: 254 }, + { red: 255, green: 0, blue: 243 }, + { red: 0, green: 180, blue: 180 }, + { red: 255, green: 118, blue: 0 }, + { red: 0, green: 255, blue: 160 } +] function getMatchColorCount() { return matchColors.length From e93782f3fefbc0b6e3ecb21c3aef3bfa851aa978 Mon Sep 17 00:00:00 2001 From: Alexander Vogt Date: Fri, 13 Oct 2023 16:47:01 +0200 Subject: [PATCH 3/7] better color choice --- report-viewer/src/utils/ColorUtils.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/report-viewer/src/utils/ColorUtils.ts b/report-viewer/src/utils/ColorUtils.ts index 53184c9f9..f743aea54 100644 --- a/report-viewer/src/utils/ColorUtils.ts +++ b/report-viewer/src/utils/ColorUtils.ts @@ -60,13 +60,13 @@ function generateColorsForInterval( } const matchColors: { red: number; green: number; blue: number }[] = [ - { red: 0, green: 9, blue: 255 }, - { red: 254, green: 255, blue: 0 }, - { red: 0, green: 255, blue: 254 }, - { red: 255, green: 0, blue: 243 }, - { red: 0, green: 180, blue: 180 }, - { red: 255, green: 118, blue: 0 }, - { red: 0, green: 255, blue: 160 } + { red: 255, green: 61, blue: 0 }, + { red: 0, green: 133, blue: 255 }, + { red: 255, green: 0, blue: 122 }, + { red: 255, green: 245, blue: 0 }, + { red: 0, green: 255, blue: 255 }, + { red: 112, green: 0, blue: 255 }, + { red: 0, green: 255, blue: 133 } ] function getMatchColorCount() { From 22c98136d93455cfc40fd2a64f8c669e5d9f801d Mon Sep 17 00:00:00 2001 From: Alexander Vogt Date: Mon, 6 Nov 2023 10:48:22 +0100 Subject: [PATCH 4/7] fix null pointer --- report-viewer/src/components/CodePanel.vue | 2 +- report-viewer/src/components/MatchList.vue | 2 +- report-viewer/src/model/factories/ComparisonFactory.ts | 8 ++++---- report-viewer/src/utils/ColorUtils.ts | 5 ++++- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/report-viewer/src/components/CodePanel.vue b/report-viewer/src/components/CodePanel.vue index 6dacf9852..47edaf420 100644 --- a/report-viewer/src/components/CodePanel.vue +++ b/report-viewer/src/components/CodePanel.vue @@ -30,7 +30,7 @@ :style="{ background: line.match !== null - ? getMatchColor(line.match.colorIndex as number, 0.3) + ? getMatchColor(0.3, line.match.colorIndex) : 'hsla(0, 0%, 0%, 0)' }" > diff --git a/report-viewer/src/components/MatchList.vue b/report-viewer/src/components/MatchList.vue index 5a53ff98c..5efa9bd91 100644 --- a/report-viewer/src/components/MatchList.vue +++ b/report-viewer/src/components/MatchList.vue @@ -15,7 +15,7 @@