• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

moosetechnology / GitProjectHealth / 10075779876

24 Jul 2024 11:28AM UTC coverage: 31.874% (-0.4%) from 32.312%
10075779876

Pull #9

github

web-flow
Merge 3f514973e into 30d38cc2f
Pull Request #9: Refactoring/metrics interface

84 of 391 new or added lines in 10 files covered. (21.48%)

13 existing lines in 2 files now uncovered.

2526 of 7925 relevant lines covered (31.87%)

0.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/GitLabHealth-Model-Analysis/GitMetric4User.class.st
1
Class {
2
        #name : #GitMetric4User,
3
        #superclass : #GitMetric,
4
        #instVars : [
5
                'itsGroups',
6
                'itsCommits',
7
                'itsMergeRequests'
8
        ],
9
        #category : #'GitLabHealth-Model-Analysis'
10
}
11

12
{ #category : #churn }
13
GitMetric4User >> codeChurnSince: since until: until onACommitWindowOf: commitLimit overA: aDateWeekMonthOrYear [
×
14

×
15
        | commits res groupedByDate totalContributions userCommits |
×
NEW
16
        "for each commit, we get its churn result (a dictionnary)"
×
17
        'GitMetric4User: code churn' recordInfo.
×
18
        totalContributions := OrderedCollection new.
×
19
        groupedByDate := self
×
20
                                 setupGroupedDateFrom: since
×
21
                                 to: until
×
22
                                 over: aDateWeekMonthOrYear.
×
23
        gitAnalyzer := GitAnalyzer new
×
24
                               glhImporter: glhImporter;
×
25
                               onModel: glhModel;
×
26
                               maxChildCommit: commitLimit.
×
27
        glhImporter withCommitDiffs: false.
×
28
        commits := self
×
29
                           loadCommitOfProjects: itsProjects keys
×
30
                           since: since
×
31
                           until: until.
×
32
        glhImporter withCommitDiffs: true.
×
33
        userCommits := commits reject: [ :commit |
×
34
                               commit commitCreator ~= user ].
×
35
        commits := self
×
36
                           foundSuccessorOf: userCommits
×
37
                           andCompleteImportForMax: commitLimit.
×
38

×
39

×
40
        res := commits collect: [ :commit |
×
41
                       commit -> (gitAnalyzer
×
42
                                fromCommit: commit;
×
43
                                analyseChurn) ].
×
44
        res do: [ :commits4Churns |
×
45
                | commit allChurnsInCommit sumChurnInCommit overDate contribution churnOnCommit |
×
46
                commit := commits4Churns key.
×
47
                allChurnsInCommit := commits4Churns value.
×
48
                sumChurnInCommit := (allChurnsInCommit at: #churns) sum: [ :churn |
×
49
                                            | numerator |
×
50
                                            numerator := churn value at: #churnLoC.
×
51
                                            numerator ].
×
52
                contribution := allChurnsInCommit at: #totalContribution.
×
53
                totalContributions add: contribution.
×
54
                churnOnCommit := {
×
55
                                         (#churnOnCommit -> sumChurnInCommit).
×
56
                                         (#LoCOnCommit -> contribution) } asDictionary.
×
57
                overDate := self
×
58
                                    transformDate: commit created_at
×
59
                                    to: aDateWeekMonthOrYear.
×
60
                groupedByDate
×
61
                        at: overDate printString
×
62
                        ifPresent: [ :array | array add: churnOnCommit ]
×
63
                        ifAbsentPut: [
×
64
                                OrderedCollection new
×
65
                                        add: churnOnCommit;
×
66
                                        yourself ] ].
×
67
        groupedByDate := groupedByDate collect: [ :churnsAtDate |
×
68
                                 | totalChurn totalContribution percentage |
×
69
                                 totalChurn := churnsAtDate sum: [ :churn |
×
70
                                                       churn at: #churnOnCommit ].
×
71
                                 totalContribution := churnsAtDate sum: [ :churn |
×
72
                                                              churn at: #LoCOnCommit ].
×
73
                                 totalContribution = 0
×
74
                                         ifTrue: [ percentage := 0 asFloat ]
×
75
                                         ifFalse: [
×
76
                                         percentage := (totalChurn * 100
×
77
                                                        / totalContribution) asFloat ].
×
78
                                 {
×
79
                                         (#churn -> totalChurn).
×
80
                                         (#contribution -> totalContribution).
×
81
                                         (#percentage -> percentage) } asDictionary ].
×
82
        ^ {
×
83
                  (#details -> groupedByDate).
×
84
                  (#totalContribution -> (totalContributions
×
85
                            ifEmpty: [ 0 ]
×
86
                            ifNotEmpty: [ totalContributions sum ])).
×
87
                  (#totalChurn -> (groupedByDate sum: [ :date | date at: #churn ])).
×
88
                  (#churn
×
89
                   ->
×
90
                   (groupedByDate collect: [ :date | date at: #percentage ]) average).
×
91
                  (#overEach -> aDateWeekMonthOrYear name).
×
92
                  (#forOver -> (groupedByDate keys size printString
×
93
                    , aDateWeekMonthOrYear printString)).
×
94
                  (#userCommits -> commits size).
×
95
                  (#churnWindow -> commitLimit) } asDictionary
×
96
]
×
97

98
{ #category : #metrics }
99
GitMetric4User >> codeContributionsSince: since until: until overA: aDateWeekMonthOrYear [
×
100

×
101
        | commits contributions groupedByDate |
×
102
        'GitMetric4User: code contribution' recordInfo.
×
NEW
103
        
×
104
        groupedByDate := self
×
105
                                 setupGroupedDateFrom: since
×
106
                                 to: until
×
107
                                 over: aDateWeekMonthOrYear.
×
108

×
109
        gitAnalyzer := GitAnalyzer new
×
110
                               onModel: glhModel;
×
111
                               glhImporter: glhImporter.
×
112

×
113
        glhImporter withCommitDiffs: false.
×
114
        commits := self
×
115
                           loadCommitOfProjects: itsProjects keys
×
116
                           since: since
×
117
                           until: until.
×
118
        glhImporter withCommitDiffs: true.
×
119
        commits := commits reject: [ :commit | commit commitCreator ~= user ].
×
120

×
121
        contributions := commits collect: [ :commit |
×
122
                                 commit -> (gitAnalyzer
×
123
                                          fromCommit: commit;
×
124
                                          analyseCommitContribution) ].
×
125

×
126
        contributions do: [ :assoc |
×
127
                | dateOver |
×
128
                dateOver := self
×
129
                                    transformDate: assoc key created_at
×
130
                                    to: aDateWeekMonthOrYear.
×
131
                groupedByDate
×
132
                        at: dateOver printString
×
133
                        ifPresent: [ :v | v add: assoc value ]
×
134
                        ifAbsentPut: [
×
135
                                OrderedCollection new
×
136
                                        add: assoc value;
×
137
                                        yourself ] ].
×
138

×
139
        groupedByDate := groupedByDate collect: [ :contribs |
×
140
                                 | totalAdd totalDele |
×
141
                                 totalAdd := contribs sum: [ :v | v at: #addition ].
×
142
                                 totalDele := contribs sum: [ :v | v at: #deletion ].
×
143
                                 {
×
144
                                         (#addition -> totalAdd).
×
145
                                         (#deletion -> totalDele) } asDictionary ].
×
146

×
147
        ^ {
×
148
                  (#overEach -> aDateWeekMonthOrYear name).
×
149
                  (#forOver -> (groupedByDate keys size printString
×
150
                    , aDateWeekMonthOrYear printString)).
×
151
                  (#avgAddition
×
152
                   ->
×
153
                   (groupedByDate collect: [ :d | d at: #addition ]) average asFloat).
×
154
                  (#avgDeletion
×
155
                   ->
×
156
                   (groupedByDate collect: [ :d | d at: #deletion ]) average asFloat).
×
157
                  (#details -> groupedByDate).
×
158
                  (#userCommits -> commits size) } asDictionary
×
159
]
×
160

161
{ #category : #metrics }
162
GitMetric4User >> commentsContributionsSince: since until: until overA: aDateWeekMonthOrYear [
×
163

×
164
        | commits contributions groupedByDate |
×
165
        'GitMetric4User: comment contribution' recordInfo.
×
166

×
167
        groupedByDate := self
×
168
                                 setupGroupedDateFrom: since
×
169
                                 to: until
×
170
                                 over: aDateWeekMonthOrYear.
×
171

×
172
        gitAnalyzer := GitAnalyzer new
×
173
                               onModel: glhModel;
×
174
                               glhImporter: glhImporter.
×
175

×
176
        glhImporter withCommitDiffs: false.
×
177
        commits := self
×
178
                           loadCommitOfProjects: itsProjects keys
×
179
                           since: since
×
180
                           until: until.
×
181
        glhImporter withCommitDiffs: true.
×
182
        commits := commits reject: [ :commit | commit commitCreator ~= user ].
×
183
        commits do: [ :commit | glhImporter completeImportedCommit: commit ].
×
184

×
185

×
186
        contributions := commits collect: [ :commit |
×
187
                                 commit -> (gitAnalyzer
×
188
                                          fromCommit: commit;
×
NEW
189
                                          analyseCommentContribution) ].
×
190

×
191

×
192
        contributions do: [ :assoc |
×
193
                | dateOver |
×
194
                dateOver := self
×
195
                                    transformDate: assoc key created_at
×
196
                                    to: aDateWeekMonthOrYear.
×
197
                groupedByDate
×
198
                        at: dateOver printString
×
199
                        ifPresent: [ :v | v add: assoc value ]
×
200
                        ifAbsentPut: [
×
201
                                OrderedCollection new
×
202
                                        add: assoc value;
×
203
                                        yourself ] ].
×
204

×
205
        groupedByDate := groupedByDate collect: [ :contribs |
×
206
                                 contribs
×
207
                                         ifNotEmpty: [ contribs sum ]
×
208
                                         ifEmpty: [ 0 ] ].
×
209

×
210

×
211
        ^ {
×
212
                  (#details -> groupedByDate).
×
213
                  (#totalComments -> groupedByDate values sum).
×
214
                  (#avgComments -> groupedByDate values average asFloat).
×
215
                  (#overEach -> aDateWeekMonthOrYear name).
×
216
                  (#forOver -> (groupedByDate keys size printString
×
217
                    , aDateWeekMonthOrYear printString)).
×
218
                  (#userCommits -> commits size) } asDictionary
×
219
]
×
220

221
{ #category : #metrics }
222
GitMetric4User >> commitFrequencySince: since until: until overA: aDateWeekMonthOrYear [
×
223

×
224
        | periods total groupedByDate userCommits |
×
225
        'GitMetric4User: commit frequency' recordInfo.
×
226

×
227
        groupedByDate := self
×
228
                                 setupGroupedDateFrom: since
×
229
                                 to: until
×
230
                                 over: aDateWeekMonthOrYear.
×
231

×
232
        glhImporter withCommitDiffs: false.
×
233
        userCommits := self
×
234
                               loadCommitOfProjects: itsProjects keys
×
235
                               since: since
×
236
                               until: until.
×
237
        glhImporter withCommitDiffs: true.
×
238
        userCommits := userCommits reject: [ :c | c commitCreator ~= user ].
×
239

×
240
        userCommits do: [ :c |
×
241
                | dateOver |
×
242
                dateOver := self
×
243
                                    transformDate: c created_at
×
244
                                    to: aDateWeekMonthOrYear.
×
245
                groupedByDate at: dateOver printString ifPresent: [ :v | v add: c ] ].
×
246

×
247
        periods := groupedByDate keys size.
×
248
        total := groupedByDate values sum: [ :commits | commits size ].
×
249

×
250

×
251
        ^ {
×
252
                  (#averageFrac -> (total / periods)).
×
253
                  (#averageFloat -> (total / periods) asFloat).
×
254
                  (#userCommit -> total).
×
255
                  (#forOver -> (groupedByDate keys size printString
×
256
                    , aDateWeekMonthOrYear printString)).
×
257
                  (#periode -> aDateWeekMonthOrYear name).
×
258
                  (#details -> groupedByDate) } asOrderedDictionary
×
259
]
×
260

261
{ #category : #'as yet unclassified' }
262
GitMetric4User >> commitsProducedOnProject: projectId since: sinceDate until: untilDate [
×
263

×
264
        | frequencies |
×
265
        
×
266
        
×
267
        gitAnalyzer := GitAnalyzer new 
×
268
        glhImporter: glhImporter; 
×
269
        onModel: glhModel.
×
270
         
×
271
        frequencies := gitAnalyzer
×
272
                               onProject: (itsProjects at: projectId);
×
273
                               analyseCommitFrequencySince: sinceDate
×
274
                               until: untilDate. 
×
275
        
×
276
        "complete each commit "
×
277
        frequencies values flattened do: [ :commit |
×
278
                glhImporter completeImportedCommit: commit.
×
279
                 ].
×
280
        
×
281
        "Filter the associations in the 'frequencies' collection, removing any commits not created by the specified 'user'. "
×
282
        frequencies associations do: [ :assoc |
×
283
                |commits| 
×
284
                commits := assoc value.
×
285
                assoc value: (commits reject: [ :commit | commit commitCreator ~= user ]). 
×
286
        ].
×
287
        
×
288
        ^ frequencies 
×
289
]
×
290

291
{ #category : #metrics }
292
GitMetric4User >> commitsProducedOnProject: aProjectId since: since until: until overA: aWeekOrMonthOrYear [
×
NEW
293
        "'aWeekOrMonthOrYear' should be the class of Data, Week, Month or Year"
×
294

×
295
        | frequency aggregatedFrequencies |
×
NEW
296
        aggregatedFrequencies := self
×
NEW
297
                                         setupGroupedDateFrom: since
×
NEW
298
                                         to: until
×
NEW
299
                                         over: aWeekOrMonthOrYear.
×
NEW
300

×
301
        frequency := self
×
302
                             commitsProducedOnProject: aProjectId
×
303
                             since: since
×
304
                             until: until.
×
305

×
306
        frequency associations do: [ :assoc |
×
307
                | date commits overDate |
×
308
                date := assoc key.
×
309
                commits := assoc value.
×
310

×
311
                commits ifNotEmpty: [ " convert the date as its week date. For some english reason, the week start in sunday so we should add a + 1 day "
×
312
                        overDate := self transformDate: date to: aWeekOrMonthOrYear.
×
313
                        aggregatedFrequencies
×
314
                                at: overDate printString
×
315
                                ifPresent: [ :collection | collection addAll: commits ]
×
316
                                ifAbsentPut: [ commits ] ] ].
×
317

×
318
        ^ aggregatedFrequencies
×
319
]
×
320

321
{ #category : #churn }
322
GitMetric4User >> delayUntilFirstChurnSince: since until: until onACommitWindowOf: maxCommitWindow overA: aDateWeekMonthOrYear [
×
323

×
324
        | commits groupedByDate res avg userCommits |
×
325
        'GitMetric4User: delay until first churn' recordInfo.
×
326

×
327
        groupedByDate := self
×
328
                                 setupGroupedDateFrom: since
×
329
                                 to: until
×
330
                                 over: aDateWeekMonthOrYear.
×
331

×
332
        glhImporter withCommitDiffs: false.
×
333
        commits := self
×
334
                           loadCommitOfProjects: itsProjects keys
×
335
                           since: since
×
336
                           until: until.
×
337
        glhImporter withCommitDiffs: true.
×
338

×
339
        userCommits := commits reject: [ :commit |
×
340
                               commit commitCreator ~= user ].
×
341
        commits := self
×
342
                           foundSuccessorOf: userCommits
×
343
                           andCompleteImportForMax: maxCommitWindow.
×
344

×
345

×
346
        "class commit by dates, filter none user commits"
×
347
        commits do: [ :commit |
×
348
                commit commitCreator = user ifTrue: [
×
349
                        | overDate |
×
350
                        overDate := self
×
351
                                            transformDate: commit created_at
×
352
                                            to: aDateWeekMonthOrYear.
×
353

×
354
                        groupedByDate
×
355
                                at: overDate printString
×
356
                                ifPresent: [ :arrayOfCommits | arrayOfCommits add: commit ]
×
357
                                ifAbsentPut: [
×
358
                                        OrderedCollection new
×
359
                                                add: commit;
×
360
                                                yourself ] ] ].
×
361

×
362

×
363

×
364
        res := groupedByDate collect: [ :commits4Date |
×
365
                       | durationFromA2B |
×
366
                       commits4Date collect: [ :commitA |
×
367
                               | commitB |
×
368
                               commitB := GitAnalyzer new
×
369
                                                  glhImporter: glhImporter;
×
370
                                                  onModel: glhModel;
×
371
                                                  fromCommit: commitA;
×
372
                                                  maxChildCommit: maxCommitWindow;
×
NEW
373
                                                  analyseDelayUntilFirstChurn.
×
374

×
375
                               durationFromA2B := commitB
×
376
                                                          ifNil: [ 0 ]
×
377
                                                          ifNotNil: [
×
378
                                                          commitB created_at - commitA created_at ].
×
379
                               durationFromA2B ] ].
×
380

×
381

×
382

×
383
        res := res collect: [ :durationsByDate |
×
384
                       | filtered |
×
385
                       filtered := durationsByDate reject: [ :value | value = 0 ].
×
386
                       filtered isEmpty
×
387
                               ifTrue: [ nil ]
×
388
                               ifFalse: [
×
389
                               (filtered sum: [ :v | v asDuration asSeconds]) / filtered size ] ].
×
390

×
391
        res := res reject: #isNil.
×
392

×
393
        res
×
394
                ifEmpty: [ avg := nil ]
×
395
                ifNotEmpty: [ avg := res values average asFloat ].
×
396

×
397

×
398
        ^ {
×
399
                  (#avgDelay -> avg).
×
400
                  (#overEach -> aDateWeekMonthOrYear name).
×
401
                  (#forOver -> (groupedByDate keys size printString
×
402
                    , aDateWeekMonthOrYear printString)).
×
403
                  (#details -> groupedByDate) } asDictionary
×
404
]
×
405

406
{ #category : #churn }
407
GitMetric4User >> delayUntilFirstChurnSince: since until: until overA: aDateWeekMonthOrYear [
×
408

×
409
        | commits groupedByDate res avg |
×
410
        self
×
411
                deprecated:
×
412
                'Use #delayUntilFirstChurnSince:until:onACommitWindowOf:overA: instead'
×
413
                on: '1 July 2024'
×
414
                in:
×
415
                'Pharo-11.0.0+build.726.sha.aece1b5473acf3830a0e082c1bc3a15d4ff3522b (64 Bit)'.
×
416

×
417
        'GitMetric4User: delay until first churn' recordInfo.
×
418

×
419
        groupedByDate := self
×
420
                                 setupGroupedDateFrom: since
×
421
                                 to: until
×
422
                                 over: aDateWeekMonthOrYear.
×
423

×
424
        commits := self
×
425
                           loadCommitOfProjects: itsProjects keys
×
426
                           since: since
×
427
                           until: until.
×
428

×
429
        "class commit by dates, filter none user commits"
×
430
        commits do: [ :commit |
×
431
                commit commitCreator = user ifTrue: [
×
432
                        | overDate |
×
433
                        overDate := self
×
434
                                            transformDate: commit created_at
×
435
                                            to: aDateWeekMonthOrYear.
×
436

×
437
                        groupedByDate
×
438
                                at: overDate printString
×
439
                                ifPresent: [ :arrayOfCommits | arrayOfCommits add: commit ]
×
440
                                ifAbsentPut: [
×
441
                                        OrderedCollection new
×
442
                                                add: commit;
×
443
                                                yourself ] ] ].
×
444

×
445

×
446

×
447
        res := groupedByDate collect: [ :commits4Date |
×
448
                       | durationFromA2B |
×
449
                       commits4Date collect: [ :commitA |
×
450
                               | commitB |
×
451
                               commitB := GitAnalyzer new
×
452
                                                  glhImporter: glhImporter;
×
453
                                                  onModel: glhModel;
×
454
                                                  fromCommit: commitA;
×
455
                                                  maxChildCommit: 5;
×
NEW
456
                                                  analyseDelayUntilFirstChurn.
×
457

×
458
                               durationFromA2B := commitB
×
459
                                                          ifNil: [ 0 ]
×
460
                                                          ifNotNil: [
×
461
                                                          commitB created_at - commitA created_at ].
×
462
                               durationFromA2B ] ].
×
463

×
464

×
465

×
466
        res := res collect: [ :durationsByDate |
×
467
                       | filtered |
×
468
                       filtered := durationsByDate reject: [ :value | value = 0 ].
×
469
                       filtered isEmpty
×
470
                               ifTrue: [ nil ]
×
471
                               ifFalse: [
×
472
                               (filtered sum: [ :v | v asDuration ]) / filtered size ] ].
×
473

×
474
        res := res reject: #isNil.
×
475

×
476
        res
×
477
                ifEmpty: [ avg := nil ]
×
478
                ifNotEmpty: [ avg := res values sum / res keys size ].
×
479

×
480

×
481
        ^ {
×
482
                  (#avgDelay -> avg).
×
483
                  (#overEach -> aDateWeekMonthOrYear name).
×
484
                  (#forOver -> (groupedByDate keys size printString
×
485
                    , aDateWeekMonthOrYear printString)).
×
486
                  (#details -> groupedByDate) } asDictionary
×
487
]
×
488

489
{ #category : #churn }
490
GitMetric4User >> foundSuccessorOf: userCommits andCompleteImportForMax: commitLimit [
×
491

×
NEW
492
        | analyzingCommits |
×
493
        analyzingCommits := Set new.
×
494
        glhImporter withCommitDiffs: true.
×
495

×
496
        userCommits do: [ :c |
×
497
                gitAnalyzer
×
498
                        visitChildCommits: c childCommits
×
499
                        toStoreThemIn: analyzingCommits
×
500
                        upto: commitLimit ].
×
NEW
501

×
NEW
502
        analyzingCommits do: [ :c |
×
NEW
503
                MyLogs
×
NEW
504
                        logProgress: 'import commit creators: '
×
NEW
505
                        over: analyzingCommits size.
×
506
                glhImporter completeImportedCommit: c ].
×
NEW
507
        
×
508
        ^ analyzingCommits
×
509
]
×
510

511
{ #category : #initialization }
512
GitMetric4User >> initialize [
×
513

×
514
        user := GLHUser new.
×
515
        itsProjects := Dictionary new.
×
516
        itsCommits := Dictionary new.
×
517
        itsGroups := Dictionary new.
×
518
        itsMergeRequests := Dictionary new
×
519
]
×
520

521
{ #category : #accessing }
522
GitMetric4User >> itsProjects: projects [
×
523
        itsProjects := projects .
×
524
]
×
525

526
{ #category : #churn }
527
GitMetric4User >> loadCommitOfProjects: aCollection since: aTimespan [
×
528
        |commits|
×
529
        
×
530
        commits := (aCollection collect: [ :id |
×
531
                 glhImporter
×
532
                        importCommitsOProject: (itsProjects at: id)
×
533
                        since: aTimespan
×
534
                        until: nil ]) flattened.
×
535

×
536
        commits do: [ :commit |
×
537
                glhImporter completeImportedCommit: commit. 
×
538
                 ].
×
539

×
540
        ^ self userCommits.
×
541
]
×
542

543
{ #category : #metrics }
544
GitMetric4User >> mergeRequestDurationSince: since until: until overA: aDateWeekMonthOrYear [
×
545

×
546
        | mergeRequest res groupedByDate filterGroups avg |
×
547
        groupedByDate := self
×
548
                                 setupGroupedDateFrom: since
×
549
                                 to: until
×
550
                                 over: aDateWeekMonthOrYear.
×
551

×
552
        gitAnalyzer := GitAnalyzer new
×
553
                               glhImporter: glhImporter;
×
554
                               onModel: glhModel.
×
555

×
556
        glhImporter withCommitDiffs: false.
×
557
        mergeRequest := self
×
558
                                loadMergeRequestsOfProjects: itsProjects keys
×
559
                                since: since
×
560
                                until: until.
×
561
        glhImporter withCommitDiffs: true.
×
562

×
563
        mergeRequest ifEmpty: [
×
564
                ^ {
×
565
                          (#avgDuration -> nil).
×
566
                          (#overEach -> aDateWeekMonthOrYear name).
×
567
                          (#forOver -> (groupedByDate keys size printString
×
568
                            , aDateWeekMonthOrYear printString)).
×
569
                          (#totalMergeRequest -> 0).
×
570
                          (#details -> nil) } asDictionary ].
×
571

×
572
        res := mergeRequest collect: [ :mr |
×
573
                       gitAnalyzer analyseMergeResquestValidation: mr ].
×
574

×
575

×
576
        res do: [ :dic |
×
577
                | overDate |
×
578
                overDate := self
×
579
                                    transformDate: (dic at: #created_at)
×
580
                                    to: aDateWeekMonthOrYear.
×
581

×
582
                groupedByDate
×
583
                        at: overDate printString
×
584
                        ifPresent: [ :durations | durations add: (dic at: #duration) ]
×
585
                        ifAbsentPut: [
×
586
                                OrderedCollection new
×
587
                                        add: (dic at: #duration);
×
588
                                        yourself ] ].
×
589

×
590

×
591
        filterGroups := groupedByDate reject: [ :array | array isEmpty ].
×
592

×
593
        filterGroups associations do: [ :assoc |
×
594
                | sum denominator |
×
595
                denominator := assoc value size.
×
596

×
597
                sum := assoc value sum: [ :v |
×
598
                               v ifNil: [
×
599
                                       denominator := denominator - 1.
×
600
                                       0 asDuration ] ].
×
601
                denominator = 0 ifTrue: [ denominator := 1 ].
×
602

×
603
                filterGroups at: assoc key put: sum / denominator ].
×
604

×
605

×
606
        filterGroups keys
×
607
                ifEmpty: [ avg := 0 ]
×
608
                ifNotEmpty: [
×
609
                avg := filterGroups values sum / filterGroups keys size ].
×
610

×
611

×
612
        ^ {
×
613
                  (#avgDuration -> avg).
×
614
                  (#overEach -> aDateWeekMonthOrYear name).
×
615
                  (#forOver -> (groupedByDate keys size printString
×
616
                    , aDateWeekMonthOrYear printString)).
×
617
                  (#totalMergeRequest -> mergeRequest size).
×
618
                  (#details -> groupedByDate) } asDictionary
×
619
]
×
620

621
{ #category : #accessing }
622
GitMetric4User >> user [
×
623
        ^ user
×
624
]
×
625

626
{ #category : #accessing }
627
GitMetric4User >> user: anUser [
×
628
        user := anUser. 
×
629
]
×
630

631
{ #category : #accessing }
632
GitMetric4User >> userCommits [
×
633
        ^ user commits
×
634
]
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc