@beauraines/sprint-tracker 0.6.10 → 0.6.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,12 +2,30 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
- ### [0.6.10](https://github.com/beauraines/sprint-tracker/compare/v0.6.9...v0.6.10) (2023-12-16)
5
+ ### [0.6.13](https://github.com/beauraines/sprint-tracker/compare/v0.6.12...v0.6.13) (2024-04-14)
6
6
 
7
7
 
8
8
  ### Bug Fixes
9
9
 
10
+ * **deps:** bump cli-table3 from 0.6.3 to 0.6.4 ([#63](https://github.com/beauraines/sprint-tracker/issues/63)) ([1487e95](https://github.com/beauraines/sprint-tracker/commit/1487e9531782b0575ad27664814461856c454ea4))
11
+
12
+ ### [0.6.12](https://github.com/beauraines/sprint-tracker/compare/v0.6.9...v0.6.12) (2024-03-27)
13
+
14
+
15
+ ### Features
16
+
17
+ * adds running statistics plot ([#61](https://github.com/beauraines/sprint-tracker/issues/61)) ([76c1f00](https://github.com/beauraines/sprint-tracker/commit/76c1f0032b96a7afc7923f5100dcf4ef2ea59d56))
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * comments out plot command and increments version number ([#62](https://github.com/beauraines/sprint-tracker/issues/62)) ([ee18e17](https://github.com/beauraines/sprint-tracker/commit/ee18e17e7327f890f353841caed46dd04cc8fbe7))
23
+ * **deps:** bump @json2csv/node from 7.0.1 to 7.0.4 ([#31](https://github.com/beauraines/sprint-tracker/issues/31)) ([68ed973](https://github.com/beauraines/sprint-tracker/commit/68ed973199df1a650ef7d677475bef1c23b144fd))
24
+ * **deps:** bump @json2csv/node from 7.0.4 to 7.0.5 ([91a5e3b](https://github.com/beauraines/sprint-tracker/commit/91a5e3bf32c24874ae4f6c7bc52a155e9da6b35a))
25
+ * **deps:** bump @json2csv/node from 7.0.5 to 7.0.6 ([#59](https://github.com/beauraines/sprint-tracker/issues/59)) ([1e2c7cb](https://github.com/beauraines/sprint-tracker/commit/1e2c7cb31af4074de33bd36c202dc82f6559eef8))
26
+ * **deps:** bump cli-markdown from 3.2.0 to 3.2.2 ([e178633](https://github.com/beauraines/sprint-tracker/commit/e178633fde4fea487e0fe82fb0d6eab6a29d9a33))
10
27
  * **deps:** bump sqlite from 4.2.1 to 5.1.1 ([#28](https://github.com/beauraines/sprint-tracker/issues/28)) ([1fbc304](https://github.com/beauraines/sprint-tracker/commit/1fbc3049c9f218c5684699a5e320f34953d08a9f))
28
+ * **deps:** bump sqlite3 from 5.1.6 to 5.1.7 ([3b8b3fb](https://github.com/beauraines/sprint-tracker/commit/3b8b3fb82aa37f295408c6372527bcd26bcf7dcc))
11
29
 
12
30
  ### [0.6.9](https://github.com/beauraines/sprint-tracker/compare/v0.6.8...v0.6.9) (2023-12-16)
13
31
 
@@ -0,0 +1,206 @@
1
+ library(tidyverse)
2
+ library(zoo)
3
+ library(DBI)
4
+ library(RSQLite)
5
+ library(ggrepel)
6
+
7
+ args = commandArgs(trailingOnly=TRUE)
8
+ if (length(args)==0) {
9
+ stop("At least one argument must be supplied, the key", call.=FALSE)
10
+ }
11
+ project_id = if_else(is.na(args[1]),"4",args[1])
12
+
13
+ con <- dbConnect(RSQLite::SQLite(),"~/projects/sprint-tracker/tracker.db")
14
+
15
+ #TODO simplify this sql and build the data set in R, maybe
16
+ res <- dbSendQuery(con, str_c("WITH commitment as (
17
+ select
18
+ p.name,
19
+ s.id sprint_id,
20
+ s.sprint_name,
21
+ s.start_date,
22
+ s.end_date,
23
+ so.story_points,
24
+ o.name as outcome,
25
+ o.id
26
+ from
27
+ sprint_outcomes so
28
+ JOIN sprints s on sprint_id = s.id
29
+ JOIN projects p on project_id = p.id and p.id = ",project_id,
30
+ " JOIN outcomes o on outcome_id = o.id and outcome_id in (6) -- 1 Delivered, 6 Committment
31
+ ),
32
+ completed as
33
+ (
34
+ select
35
+ p.name,
36
+ s.id sprint_id,
37
+ s.sprint_name,
38
+ s.start_date,
39
+ s.end_date,
40
+ so.story_points,
41
+ o.name as outcome,
42
+ o.id
43
+ from
44
+ sprint_outcomes so
45
+ JOIN sprints s on sprint_id = s.id
46
+ JOIN projects p on project_id = p.id and p.id = ",project_id,
47
+ " JOIN outcomes o on outcome_id = o.id and outcome_id in (1) -- 1 Delivered, 6 Committment
48
+ )
49
+
50
+ select
51
+ commitment.name,
52
+ commitment.sprint_id,
53
+ commitment.sprint_name,
54
+ commitment.start_date,
55
+ commitment.end_date,
56
+ commitment.story_points commitment,
57
+ completed.story_points completed,
58
+ (completed.story_points*1.0 - commitment.story_points*1.0)/commitment.story_points * 100.0 commitment_variance
59
+ from
60
+ commitment
61
+ LEFT JOIN completed on completed.sprint_id = commitment.sprint_id
62
+ where
63
+ 1 =1
64
+ order by commitment.name,commitment.start_date
65
+
66
+ ;
67
+ "))
68
+
69
+
70
+ # TODO query sqlite directly
71
+ sprintData <- dbFetch(res)
72
+
73
+ # Clear the result
74
+ dbClearResult(res)
75
+
76
+ # Disconnect from the database
77
+ dbDisconnect(con)
78
+
79
+ ## Clean data
80
+ # Remove Foo and Abe's project
81
+ sprintData = sprintData %>%
82
+ filter(!name %in% c('Foo','Abe\'s projct'))
83
+
84
+ # How to deal with outliers
85
+
86
+ ## Add numbering
87
+ sprintData = sprintData %>%
88
+ group_by(name) %>%
89
+ mutate(sprint_number = row_number()) %>%
90
+ add_count(name="project_sprint_count") %>%
91
+ mutate(project_percent_completed = sprint_number/project_sprint_count)
92
+
93
+
94
+ ## Add velocity
95
+
96
+ sprintData = sprintData %>%
97
+ group_by(name) %>%
98
+ mutate(velocity = cumsum(completed)/sprint_number)
99
+
100
+ ## Add Completion Percentage
101
+ sprintData = sprintData %>%
102
+ group_by(name) %>%
103
+ mutate(commitment_percentage = completed/commitment)
104
+
105
+
106
+
107
+ f_labels <- sprintData %>% summarise(
108
+ Velocity = sd(velocity, na.rm=TRUE) %>% formatC(digits = 3),
109
+ "Commitment Variance" = sd(commitment_variance, na.rm=TRUE) %>% formatC(digits = 3),
110
+ "Commitment Percentage" = sd(commitment_percentage, na.rm=TRUE) %>% formatC(digits = 3)
111
+ ) %>%
112
+ select(!"name") %>%
113
+ pivot_longer(
114
+ cols = c("Velocity", "Commitment Variance", "Commitment Percentage"),
115
+ values_to = "label",
116
+ names_to = "measure" )
117
+
118
+
119
+ # commitment_variance
120
+ # sprintData %>%
121
+ # ggplot(aes(x = sprint_number,
122
+ # y = commitment_variance,
123
+ # colour = name)) +
124
+ # geom_line() +
125
+ # geom_point()
126
+
127
+
128
+
129
+ # Sprint Velocity
130
+ # sprintData %>%
131
+ # ggplot(aes(x = sprint_number,
132
+ # y = velocity,
133
+ # colour = name)) +
134
+ # geom_line() +
135
+ # geom_point()
136
+
137
+ # Commitment Percentage
138
+ # sprintData %>%
139
+ # ggplot(aes(x = commitment_percentage,
140
+ # y = velocity,
141
+ # colour = name)) +
142
+ # geom_line() +
143
+ # geom_point()
144
+
145
+
146
+ sprintDataPivot = sprintData %>%
147
+ select(!c(completed,commitment,sprint_id,project_sprint_count,project_percent_completed)) %>%
148
+ pivot_longer(
149
+ c(velocity,commitment_percentage,commitment_variance),
150
+ names_to = "measure",
151
+ values_to = "value"
152
+ )
153
+
154
+ projectName = unique(sprintDataPivot$name)
155
+
156
+ plot <- sprintDataPivot %>%
157
+ ggplot(aes(x = reorder(str_wrap(sprint_name,15),sprint_number),
158
+ y = value
159
+ )) +
160
+ geom_line(group=1,color = "#b9b9b9") +
161
+ geom_point(color = "#b9b9b9") +
162
+ # Add point values
163
+ geom_text_repel(
164
+ aes(label=round(value,2)),
165
+ direction = "y",
166
+ family = "roboto",
167
+ size = 10 * 5/14 * 0.8) +
168
+ # plot labels
169
+ labs(title=str_c(projectName,"Sprint Statistics", sep =" "),
170
+ x ="",
171
+ y = "") +
172
+ #themes
173
+ theme(
174
+ plot.title = element_text(family = "roboto"),
175
+ axis.title.x = element_text(family = "roboto"),
176
+ axis.text.x = element_text(angle = 45, vjust = 1, hjust=1),
177
+ axis.title.y = element_text(family = "roboto"),
178
+ panel.grid.major.y = element_line(colour = "#D9D9D9"),
179
+ panel.grid.minor.y = element_line(colour = "#D9D9D9"),
180
+ panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(),
181
+ # background color
182
+ panel.background = element_rect(fill = "#D9D9D920", colour = NA),
183
+ legend.position = "bottom",
184
+ plot.background = element_rect(colour = "#D9D9D9", fill=NA)
185
+ )
186
+
187
+ plot <- plot + facet_wrap(
188
+ vars(str_to_title(sub("_"," ",measure))),
189
+ ncol = 1,
190
+ scales = "free_y"
191
+ )
192
+
193
+ plot <- plot +
194
+ geom_label(
195
+ x = 1,
196
+ y = Inf,
197
+ aes(label = str_c("St Dev = ",label), hjust = "left", vjust = 1.3),
198
+ data = f_labels
199
+ )
200
+
201
+ # plot
202
+
203
+
204
+ ggsave(str_c(Sys.getenv("HOME"),"/",str_replace(projectName," ",""),"SprintStats.png"),plot=plot,bg="white", width = 2882, height = 1700, units = "px")
205
+
206
+ print(str_c("Saving to ",str_c(Sys.getenv("HOME"),"/",str_replace(projectName," ",""),"SprintStats.png"),sep = " "))
package/cmds/stats.js ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { database: db } = require('helpers')
4
+ const { prompt } = require('../utils/input.js')
5
+ const {readConfig} = require('helpers').config
6
+ const exec = require('child_process').exec;
7
+ const process = require('process');
8
+
9
+ const command = 'stats'
10
+ const desc = 'Creates sprint statistics (Commitment variance, Commitment Percentage and Velocity ) with R. Requires a local R install'
11
+ const builder = {}
12
+
13
+ const handler = async function () {
14
+ // Get Data from Database and write to file
15
+ console.log('Getting data')
16
+
17
+ const filename = 'sprintTracker.json'
18
+ const config = await readConfig(filename)
19
+ const database = config.database
20
+
21
+ // list projects
22
+
23
+ let statement = 'select * from projects;';
24
+
25
+ let projects = await db.query(database,statement)
26
+
27
+ for (const project of projects) {
28
+ console.log(project.id, project.name)
29
+ }
30
+
31
+ // Select the project
32
+
33
+ // Select the project
34
+ let project_id
35
+
36
+ let text = 'Enter the project id: '
37
+ while (!project_id) {
38
+ project_id = prompt(text)
39
+
40
+ // validate the response
41
+ if (!projects.find(x => (x.id == project_id))) {
42
+ console.error('Invalid project id')
43
+ project_id = null
44
+ }
45
+ }
46
+
47
+ console.log('Making statistics visualizations')
48
+ const cmd = `Rscript ${__dirname}/../R/commitmentVarianceCli.R ${project_id}`
49
+ exec(cmd, function(err, stdout, stderr) {
50
+ if (err) {
51
+ console.log(stderr);
52
+ console.log(err.message)
53
+ process.exit(err.code)
54
+ }
55
+ console.log(stdout);
56
+ });
57
+ }
58
+
59
+ module.exports = {
60
+ command,
61
+ desc,
62
+ builder,
63
+ handler
64
+ }
@@ -11,7 +11,7 @@ const path = require('path');
11
11
  const process = require('process');
12
12
 
13
13
  const command = 'visualizations'
14
- const desc = 'Creates Feature Team visualizations with R. Must have docker, rstudio-tidyverse container and more installed'
14
+ const desc = 'Creates sprint visualizations with R. Requires a local R install'
15
15
  const builder = {}
16
16
 
17
17
  const handler = async function () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beauraines/sprint-tracker",
3
- "version": "0.6.10",
3
+ "version": "0.6.13",
4
4
  "description": "Database and R visualizations to track sprint performance",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -0,0 +1,52 @@
1
+ WITH commitment as
2
+
3
+ (
4
+ select
5
+ p.name,
6
+ s.id sprint_id,
7
+ s.sprint_name,
8
+ s.start_date,
9
+ s.end_date,
10
+ so.story_points,
11
+ o.name as outcome,
12
+ o.id
13
+ from
14
+ sprint_outcomes so
15
+ JOIN sprints s on sprint_id = s.id
16
+ JOIN projects p on project_id = p.id --and p.id = 11
17
+ JOIN outcomes o on outcome_id = o.id and outcome_id in (6) -- 1 Delivered, 6 Committment
18
+ ),
19
+
20
+ completed as
21
+ (
22
+ select
23
+ p.name,
24
+ s.id sprint_id,
25
+ s.sprint_name,
26
+ s.start_date,
27
+ s.end_date,
28
+ so.story_points,
29
+ o.name as outcome,
30
+ o.id
31
+ from
32
+ sprint_outcomes so
33
+ JOIN sprints s on sprint_id = s.id
34
+ JOIN projects p on project_id = p.id --and p.id = 11
35
+ JOIN outcomes o on outcome_id = o.id and outcome_id in (1) -- 1 Delivered, 6 Committment
36
+ )
37
+
38
+ select
39
+ commitment.name,
40
+ commitment.sprint_id,
41
+ commitment.sprint_name,
42
+ commitment.start_date,
43
+ commitment.end_date,
44
+ commitment.story_points commitment,
45
+ completed.story_points completed,
46
+ (completed.story_points*1.0 - commitment.story_points*1.0)/commitment.story_points * 100.0 commitment_variance
47
+ from
48
+ commitment
49
+ LEFT JOIN completed on completed.sprint_id = commitment.sprint_id
50
+ where
51
+ commitment.name in ('ALPR Data Enhancement','ECOM Enhancements')
52
+ order by commitment.name,commitment.sprint_name