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

add editors breakdown #24

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
243 changes: 243 additions & 0 deletions src/components/BreakdownsComponent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
<template>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would it make sense to name it BreakdownComponent.vue? As I would assume it is a singular breakdown per component e.g. languages or editors

<div>
<div class="tiles-container">
<!-- Acceptance Rate Tile -->
<v-card elevation="4" color="white" variant="elevated" class="mx-auto my-3" style="width: 300px; height: 175px;">
<v-card-item>
<div>
<div class="text-overline mb-1" style="visibility: hidden;">filler</div>
<div class="text-h6 mb-1">Number of {{ breakdownKey }}s</div>
martedesco marked this conversation as resolved.
Show resolved Hide resolved
<div class="text-caption">
Over the last 28 days
</div>
<p>{{ numberOfBreakdowns }}</p>
</div>
</v-card-item>
</v-card>
</div>

<v-main class="p-1" style="min-height: 300px;">
<v-container style="min-height: 300px;" class="px-4 elevation-2">
<v-row>
<v-col cols="6">
<v-card>
<v-card-item class="d-flex justify-center align-center">
<div class="text-overline mb-1" style="visibility: hidden;">filler</div>
<div class="text-h6 mb-1">Top 5 {{ breakdownKey }}s by accepted prompts</div>
<div style="width: 300px; height: 300px;">
<Pie :data="breakdownsChartDataTop5AcceptedPrompts" :options="chartOptions" />
</div>
</v-card-item>
</v-card>
</v-col>

<v-col cols="6">
<v-card>
<v-card-item class="d-flex justify-center align-center">
<div class="text-overline mb-1" style="visibility: hidden;">filler</div>
<div class="text-h6 mb-1">Top 5 {{ breakdownKey }}s by acceptance rate</div>
<div style="width: 300px; height: 300px;">
<Pie :data="breakdownsChartDataTop5AcceptanceRate" :options="chartOptions" />
</div>
</v-card-item>
</v-card>
</v-col>
</v-row>

<br>
<h2>{{ breakdownDisplayName }}s Breakdown </h2>
<br>

<v-data-table :headers="headers" :items="Array.from(breakdowns)" class="elevation-2" style="padding-left: 100px; padding-right: 100px;">
<template v-slot:item="{item}">
<tr>
<td>{{ item[0] }}</td>
<td>{{ item[1].acceptedPrompts }}</td>
<td>{{ item[1].acceptedLinesOfCode }}</td>
<td v-if="item[1].acceptanceRate !== undefined">{{ item[1].acceptanceRate.toFixed(2) }}%</td>
</tr>
</template>
</v-data-table>
</v-container>
</v-main>
</div>
</template>

<script lang="ts">
import { defineComponent, ref, toRef } from 'vue';
import { Metrics } from '../model/Metrics';
import { Breakdown } from '../model/Breakdown';
import { Pie } from 'vue-chartjs'

import {
Chart as ChartJS,
ArcElement,
CategoryScale,
LinearScale,
PointElement,
LineElement,
BarElement,
Title,
Tooltip,
Legend
} from 'chart.js'

ChartJS.register(
ArcElement,
CategoryScale,
LinearScale,
BarElement,
PointElement,
LineElement,
Title,
Tooltip,
Legend
)

export default defineComponent({
name: 'BreakdownsComponent',
props: {
metrics: {
type: Object,
required: true
},
breakdownKey: {
type: String,
required: true
}
},
components: {
Pie
},
computed: {
breakdownDisplayName() {
return this.breakdownKey.charAt(0).toUpperCase() + this.breakdownKey.slice(1);
},
headers() {
return [
{ title: `${this.breakdownDisplayName} Name`, key: 'breakdownName' },
{ title: 'Accepted Prompts', key: 'acceptedPrompts' },
{ title: 'Accepted Lines of Code', key: 'acceptedLinesOfCode' },
{ title: 'Acceptance Rate (%)', key: 'acceptanceRate' },
];
},
},
setup(props) {

// Create an empty map to store the breakdowns.
const breakdowns = ref(new Map<string, Breakdown>());

// Number of breakdowns
const numberOfBreakdowns = ref(0);

// Breakdowns Chart Data for breakdowns breakdown Pie Chart
let breakdownsChartData = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] });

//Top 5 by accepted prompts
let breakdownsChartDataTop5AcceptedPrompts = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] });

//Top 5 by acceptance rate
let breakdownsChartDataTop5AcceptanceRate = ref<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [] });

const chartOptions = {
responsive: true,
maintainAspectRatio: true,
};

const pieChartColors = ref([
'#4B0082', '#41B883', '#483D8B', '#87CEFA',
'#32CD32'
]);

const data = toRef(props, 'metrics').value;

// Process the breakdown separately
data.forEach((m: Metrics) => m.breakdown.forEach(breakdownData =>
{
const breakdownName = breakdownData[props.breakdownKey as keyof typeof breakdownData] as string;
let breakdown = breakdowns.value.get(breakdownName);

if (!breakdown) {
// Create a new breakdown object if it does not exist
breakdown = new Breakdown({
name: breakdownName,
acceptedPrompts: breakdownData.acceptances_count,
suggestedLinesOfCode: breakdownData.lines_suggested,
acceptedLinesOfCode: breakdownData.lines_accepted,
});
breakdowns.value.set(breakdownName, breakdown);
} else {
// Update the existing breakdown object
breakdown.acceptedPrompts += breakdownData.acceptances_count;
breakdown.suggestedLinesOfCode += breakdownData.lines_suggested;
breakdown.acceptedLinesOfCode += breakdownData.lines_accepted;
}
// Recalculate the acceptance rate
breakdown.acceptanceRate = breakdown.suggestedLinesOfCode !== 0 ? (breakdown.acceptedLinesOfCode / breakdown.suggestedLinesOfCode) * 100 : 0;
}));

//Sort breakdowns map by acceptance rate
breakdowns.value[Symbol.iterator] = function* () {
yield* [...this.entries()].sort((a, b) => b[1].acceptanceRate - a[1].acceptanceRate);
}

// Get the top 5 breakdowns by acceptance rate
const top5BreakdownsAcceptanceRate = new Map([...breakdowns.value].slice(0, 5));

breakdownsChartDataTop5AcceptanceRate.value = {
labels: Array.from(top5BreakdownsAcceptanceRate.values()).map(breakdown => breakdown.name),
datasets: [
{
data: Array.from(top5BreakdownsAcceptanceRate.values()).map(breakdown => breakdown.acceptanceRate.toFixed(2)),
backgroundColor: pieChartColors.value,
},
],
};

//Sort breakdowns map by accepted prompts
breakdowns.value[Symbol.iterator] = function* () {
yield* [...this.entries()].sort((a, b) => b[1].acceptedPrompts - a[1].acceptedPrompts);
}

breakdownsChartData.value = {
labels: Array.from(breakdowns.value.values()).map(breakdown => breakdown.name),
datasets: [
{
data: Array.from(breakdowns.value.values()).map(breakdown => breakdown.acceptedPrompts),
backgroundColor: pieChartColors.value,
},
],
};

// Get the top 5 breakdowns by accepted prompts
const top5BreakdownsAcceptedPrompts = new Map([...breakdowns.value].slice(0, 5));

breakdownsChartDataTop5AcceptedPrompts.value = {
labels: Array.from(top5BreakdownsAcceptedPrompts.values()).map(breakdown => breakdown.name),
datasets: [
{
data: Array.from(top5BreakdownsAcceptedPrompts.values()).map(breakdown => breakdown.acceptedPrompts),
backgroundColor: pieChartColors.value,
},
],
};

numberOfBreakdowns.value = breakdowns.value.size;

return { chartOptions, breakdowns, numberOfBreakdowns,
breakdownsChartData, breakdownsChartDataTop5AcceptedPrompts, breakdownsChartDataTop5AcceptanceRate };
},


});
</script>

<style scoped>

.tiles-container {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
}

</style>