1
+ <template >
2
+ <div >
3
+ <div class =" tiles-container" >
4
+ <!-- Acceptance Rate Tile -->
5
+ <v-card elevation =" 4" color =" white" variant =" elevated" class =" mx-auto my-3" style =" width : 300px ; height : 175px ;" >
6
+ <v-card-item >
7
+ <div >
8
+ <div class =" text-overline mb-1" style =" visibility : hidden ;" >filler</div >
9
+ <div class =" text-h6 mb-1" >Number of {{ breakdownKey }}s</div >
10
+ <div class =" text-caption" >
11
+ Over the last 28 days
12
+ </div >
13
+ <p >{{ numberOfBreakdowns }}</p >
14
+ </div >
15
+ </v-card-item >
16
+ </v-card >
17
+ </div >
18
+
19
+ <v-main class =" p-1" style =" min-height : 300px ;" >
20
+ <v-container style =" min-height : 300px ;" class =" px-4 elevation-2" >
21
+ <v-row >
22
+ <v-col cols =" 6" >
23
+ <v-card >
24
+ <v-card-item class =" d-flex justify-center align-center" >
25
+ <div class =" text-overline mb-1" style =" visibility : hidden ;" >filler</div >
26
+ <div class =" text-h6 mb-1" >Top 5 {{ breakdownKey }}s by accepted prompts</div >
27
+ <div style =" width : 300px ; height : 300px ;" >
28
+ <Pie :data =" breakdownsChartDataTop5AcceptedPrompts" :options =" chartOptions" />
29
+ </div >
30
+ </v-card-item >
31
+ </v-card >
32
+ </v-col >
33
+
34
+ <v-col cols =" 6" >
35
+ <v-card >
36
+ <v-card-item class =" d-flex justify-center align-center" >
37
+ <div class =" text-overline mb-1" style =" visibility : hidden ;" >filler</div >
38
+ <div class =" text-h6 mb-1" >Top 5 {{ breakdownKey }}s by acceptance rate</div >
39
+ <div style =" width : 300px ; height : 300px ;" >
40
+ <Pie :data =" breakdownsChartDataTop5AcceptanceRate" :options =" chartOptions" />
41
+ </div >
42
+ </v-card-item >
43
+ </v-card >
44
+ </v-col >
45
+ </v-row >
46
+
47
+ <br >
48
+ <h2 >{{ breakdownDisplayName }}s Breakdown </h2 >
49
+ <br >
50
+
51
+ <v-data-table :headers =" headers" :items =" Array.from(breakdowns)" class =" elevation-2" style =" padding-left : 100px ; padding-right : 100px ;" >
52
+ <template v-slot :item =" {item } " >
53
+ <tr >
54
+ <td >{{ item[0] }}</td >
55
+ <td >{{ item[1].acceptedPrompts }}</td >
56
+ <td >{{ item[1].acceptedLinesOfCode }}</td >
57
+ <td v-if =" item[1].acceptanceRate !== undefined" >{{ item[1].acceptanceRate.toFixed(2) }}%</td >
58
+ </tr >
59
+ </template >
60
+ </v-data-table >
61
+ </v-container >
62
+ </v-main >
63
+ </div >
64
+ </template >
65
+
66
+ <script lang="ts">
67
+ import { defineComponent , ref , toRef } from ' vue' ;
68
+ import { Metrics } from ' ../model/Metrics' ;
69
+ import { Breakdown } from ' ../model/Breakdown' ;
70
+ import { Pie } from ' vue-chartjs'
71
+
72
+ import {
73
+ Chart as ChartJS ,
74
+ ArcElement ,
75
+ CategoryScale ,
76
+ LinearScale ,
77
+ PointElement ,
78
+ LineElement ,
79
+ BarElement ,
80
+ Title ,
81
+ Tooltip ,
82
+ Legend
83
+ } from ' chart.js'
84
+
85
+ ChartJS .register (
86
+ ArcElement ,
87
+ CategoryScale ,
88
+ LinearScale ,
89
+ BarElement ,
90
+ PointElement ,
91
+ LineElement ,
92
+ Title ,
93
+ Tooltip ,
94
+ Legend
95
+ )
96
+
97
+ export default defineComponent ({
98
+ name: ' BreakdownsComponent' ,
99
+ props: {
100
+ metrics: {
101
+ type: Object ,
102
+ required: true
103
+ },
104
+ breakdownKey: {
105
+ type: String ,
106
+ required: true
107
+ }
108
+ },
109
+ components: {
110
+ Pie
111
+ },
112
+ computed: {
113
+ breakdownDisplayName() {
114
+ return this .breakdownKey .charAt (0 ).toUpperCase () + this .breakdownKey .slice (1 );
115
+ },
116
+ headers() {
117
+ return [
118
+ { title: ` ${this .breakdownDisplayName } Name ` , key: ' breakdownName' },
119
+ { title: ' Accepted Prompts' , key: ' acceptedPrompts' },
120
+ { title: ' Accepted Lines of Code' , key: ' acceptedLinesOfCode' },
121
+ { title: ' Acceptance Rate (%)' , key: ' acceptanceRate' },
122
+ ];
123
+ },
124
+ },
125
+ setup(props ) {
126
+
127
+ // Create an empty map to store the breakdowns.
128
+ const breakdowns = ref (new Map <string , Breakdown >());
129
+
130
+ // Number of breakdowns
131
+ const numberOfBreakdowns = ref (0 );
132
+
133
+ // Breakdowns Chart Data for breakdowns breakdown Pie Chart
134
+ let breakdownsChartData = ref <{ labels: string []; datasets: any [] }>({ labels: [], datasets: [] });
135
+
136
+ // Top 5 by accepted prompts
137
+ let breakdownsChartDataTop5AcceptedPrompts = ref <{ labels: string []; datasets: any [] }>({ labels: [], datasets: [] });
138
+
139
+ // Top 5 by acceptance rate
140
+ let breakdownsChartDataTop5AcceptanceRate = ref <{ labels: string []; datasets: any [] }>({ labels: [], datasets: [] });
141
+
142
+ const chartOptions = {
143
+ responsive: true ,
144
+ maintainAspectRatio: true ,
145
+ };
146
+
147
+ const pieChartColors = ref ([
148
+ ' #4B0082' , ' #41B883' , ' #483D8B' , ' #87CEFA' ,
149
+ ' #32CD32'
150
+ ]);
151
+
152
+ const data = toRef (props , ' metrics' ).value ;
153
+
154
+ // Process the breakdown separately
155
+ data .forEach ((m : Metrics ) => m .breakdown .forEach (breakdownData =>
156
+ {
157
+ const breakdownName = breakdownData [props .breakdownKey as keyof typeof breakdownData ] as string ;
158
+ let breakdown = breakdowns .value .get (breakdownName );
159
+
160
+ if (! breakdown ) {
161
+ // Create a new breakdown object if it does not exist
162
+ breakdown = new Breakdown ({
163
+ name: breakdownName ,
164
+ acceptedPrompts: breakdownData .acceptances_count ,
165
+ suggestedLinesOfCode: breakdownData .lines_suggested ,
166
+ acceptedLinesOfCode: breakdownData .lines_accepted ,
167
+ });
168
+ breakdowns .value .set (breakdownName , breakdown );
169
+ } else {
170
+ // Update the existing breakdown object
171
+ breakdown .acceptedPrompts += breakdownData .acceptances_count ;
172
+ breakdown .suggestedLinesOfCode += breakdownData .lines_suggested ;
173
+ breakdown .acceptedLinesOfCode += breakdownData .lines_accepted ;
174
+ }
175
+ // Recalculate the acceptance rate
176
+ breakdown .acceptanceRate = breakdown .suggestedLinesOfCode !== 0 ? (breakdown .acceptedLinesOfCode / breakdown .suggestedLinesOfCode ) * 100 : 0 ;
177
+ }));
178
+
179
+ // Sort breakdowns map by acceptance rate
180
+ breakdowns .value [Symbol .iterator ] = function * () {
181
+ yield * [... this .entries ()].sort ((a , b ) => b [1 ].acceptanceRate - a [1 ].acceptanceRate );
182
+ }
183
+
184
+ // Get the top 5 breakdowns by acceptance rate
185
+ const top5BreakdownsAcceptanceRate = new Map ([... breakdowns .value ].slice (0 , 5 ));
186
+
187
+ breakdownsChartDataTop5AcceptanceRate .value = {
188
+ labels: Array .from (top5BreakdownsAcceptanceRate .values ()).map (breakdown => breakdown .name ),
189
+ datasets: [
190
+ {
191
+ data: Array .from (top5BreakdownsAcceptanceRate .values ()).map (breakdown => breakdown .acceptanceRate .toFixed (2 )),
192
+ backgroundColor: pieChartColors .value ,
193
+ },
194
+ ],
195
+ };
196
+
197
+ // Sort breakdowns map by accepted prompts
198
+ breakdowns .value [Symbol .iterator ] = function * () {
199
+ yield * [... this .entries ()].sort ((a , b ) => b [1 ].acceptedPrompts - a [1 ].acceptedPrompts );
200
+ }
201
+
202
+ breakdownsChartData .value = {
203
+ labels: Array .from (breakdowns .value .values ()).map (breakdown => breakdown .name ),
204
+ datasets: [
205
+ {
206
+ data: Array .from (breakdowns .value .values ()).map (breakdown => breakdown .acceptedPrompts ),
207
+ backgroundColor: pieChartColors .value ,
208
+ },
209
+ ],
210
+ };
211
+
212
+ // Get the top 5 breakdowns by accepted prompts
213
+ const top5BreakdownsAcceptedPrompts = new Map ([... breakdowns .value ].slice (0 , 5 ));
214
+
215
+ breakdownsChartDataTop5AcceptedPrompts .value = {
216
+ labels: Array .from (top5BreakdownsAcceptedPrompts .values ()).map (breakdown => breakdown .name ),
217
+ datasets: [
218
+ {
219
+ data: Array .from (top5BreakdownsAcceptedPrompts .values ()).map (breakdown => breakdown .acceptedPrompts ),
220
+ backgroundColor: pieChartColors .value ,
221
+ },
222
+ ],
223
+ };
224
+
225
+ numberOfBreakdowns .value = breakdowns .value .size ;
226
+
227
+ return { chartOptions , breakdowns , numberOfBreakdowns ,
228
+ breakdownsChartData , breakdownsChartDataTop5AcceptedPrompts , breakdownsChartDataTop5AcceptanceRate };
229
+ },
230
+
231
+
232
+ });
233
+ </script >
234
+
235
+ <style scoped>
236
+
237
+ .tiles-container {
238
+ display : flex ;
239
+ justify-content : flex-start ;
240
+ flex-wrap : wrap ;
241
+ }
242
+
243
+ </style >
0 commit comments