From 34fa03b74e278f0080cd53112bee00035a198a95 Mon Sep 17 00:00:00 2001 From: Alex | Kronox Date: Mon, 11 Sep 2023 16:19:17 +0200 Subject: [PATCH] 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 }