Skip to content

Commit

Permalink
Merge pull request #1311 from jplag/report-viewer/new-colorgen
Browse files Browse the repository at this point in the history
  • Loading branch information
Kr0nox authored Nov 28, 2023
2 parents 45d3442 + a6d41b4 commit 5b9acf3
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 16 deletions.
6 changes: 5 additions & 1 deletion report-viewer/src/components/CodePanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
<td
class="w-full"
:style="{
background: line.match !== null ? line.match.color : 'hsla(0, 0%, 0%, 0)'
background:
line.match !== null
? getMatchColor(0.3, line.match.colorIndex)
: 'hsla(0, 0%, 0%, 0)'
}"
>
<pre v-html="line.line" class="code-font !bg-transparent" ref="lineRefs"></pre>
Expand All @@ -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({
/**
Expand Down
3 changes: 2 additions & 1 deletion report-viewer/src/components/MatchList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

<div class="flex w-full flex-row space-x-1 overflow-x-auto">
<OptionComponent
:style="{ background: match.color }"
v-for="[index, match] in matches?.entries()"
:style="{ background: getMatchColor(0.3, match.colorIndex) }"
v-bind:key="index"
@click="$emit('matchSelected', match)"
:label="
Expand All @@ -30,6 +30,7 @@
import type { Match } from '@/model/Match'
import OptionComponent from './optionsSelectors/OptionComponent.vue'
import ToolTipComponent from './ToolTipComponent.vue'
import { getMatchColor } from '@/utils/ColorUtils'

defineProps({
/**
Expand Down
6 changes: 3 additions & 3 deletions report-viewer/src/model/Match.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
* @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
endInFirst: number
startInSecond: number
endInSecond: number
tokens: number
color: string
colorIndex?: number
}
56 changes: 46 additions & 10 deletions report-viewer/src/model/factories/ComparisonFactory.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -35,19 +35,15 @@ export class ComparisonFactory extends BaseFactory {

const matches = json.matches as Array<Record<string, unknown>>

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 unColoredMatches = matches.map((match) => this.getMatch(match))

return new Comparison(
firstSubmissionId,
secondSubmissionId,
this.extractSimilarities(json),
filesOfFirstSubmission,
filesOfSecondSubmission,
coloredMatches
this.colorMatches(unColoredMatches)
)
}

Expand Down Expand Up @@ -101,16 +97,56 @@ export class ComparisonFactory extends BaseFactory {
}
}

private static mapMatch(match: Record<string, unknown>, color: string): Match {
private static getMatch(match: Record<string, unknown>): Match {
return {
firstFile: slash(match.file1 as string),
secondFile: slash(match.file2 as string),
startInFirst: match.start1 as number,
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) => b.tokens - a.tokens)

function isColorAvailable(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 (
!isColorAvailable(matchesFirst, firstIndex) ||
!isColorAvailable(matchesSecond, secondIndex) ||
!isColorAvailable(sortedSize, sortedIndex)
) {
currentColorIndex = (currentColorIndex + 1) % maxColorCount

if (currentColorIndex == startCounter) {
// This case should never happen, this is just a safety measure
throw currentColorIndex
}
}
matches[i].colorIndex = currentColorIndex
currentColorIndex = (currentColorIndex + 1) % maxColorCount
}
return sortedSize
}
}
24 changes: 23 additions & 1 deletion report-viewer/src/utils/ColorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,28 @@ function generateColorsForInterval(
return colors
}

/** This is the list of colors that are used as the background colot of matches in the comparison view */
const matchColors: { red: number; green: number; blue: number }[] = [
{ red: 255, green: 122, 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() {
return matchColors.length
}

function getMatchColor(alpha: number, index?: number) {
if (index == undefined) {
return 'rgba(0,0,0,0)'
}
return `rgba(${matchColors[index].red}, ${matchColors[index].green}, ${matchColors[index].blue}, ${alpha})`
}

const graphColors = {
ticksAndFont: computed(() => {
return store().uiState.useDarkMode ? '#ffffff' : '#000000'
Expand All @@ -71,4 +93,4 @@ const graphColors = {
pointFill: 'rgba(190, 22, 34, 1)'
}

export { generateColors, graphColors }
export { generateColors, graphColors, getMatchColorCount, getMatchColor }

0 comments on commit 5b9acf3

Please sign in to comment.