Collaborama About Help Contact Anonymous [login] Source: site.view [edit] Function name: analyzeReviews Arguments: url Description: Page type: webl Render function: displayReviewAnalysis Module: sandbox Page source: /* <status id="10000" iconUrl="https://reviews-prd.bixbydevelopers.com/images/icons/statuses/open.png" description="The issue is open and ready for the assignee to start work on it."> Review Requested </status> <statusCategory id="2" key="new" colorName="blue-gray"/> <resolution id="-1"> Unresolved </resolution> <assignee username="-1"> Unassigned </assignee> <created> Fri, 5 Jul 2019 10:31:35 +0000 </created> <updated> Tue, 9 Jul 2019 21:35:28 +0000 </updated> */ /* {"theo", "sehwa.p", "j1 pan", "Unassigned", "Promeet Mansata", "john alioto", "min.cheng@samsung.com", "ys33 yoon", "Andy", "shahnawaz mohammed", "jared lodwick", "geoff.wong", "alex ren", "kelly li", "roger kibbe", "daphne seo", "ameya b", "michael cuff", "Leena Malaviya"} */ var startTimeStr = ""; var endTimeStr = ""; var startTimeC; var endTimeC; var minTime = 0; var maxTime = 0; var SplitByTeam = fun(reviews) var kr = []; var us = []; every r in reviews do if (r.assignee == "ys33 yoon") or (r.assignee == "daphne seo") then kr = kr + [r] else us = us + [r] end end; return [. kr = kr, us = us .] end; var GetTimeSlice = fun(reviews, startMillis, endMillis) var res = []; every r in reviews do if (r.created > startMillis and r.created < endMillis) then res = res + [r] end end; return res end; var GetField = fun (P, field, item) var E = Elem(P, field) inside item; if Size(E) == 1 then return Str_Trim(Text(E[0])) else return nil end end; var GetTimeObj = fun(s) // Fri, 5 Jul 2019 10:31:35 +0000 var m = Str_Match(s, `\w+, (\d+) (\w+) (\d+) (\d+)\:(\d+)\:(\d+) \+0000`); var c = Wub_GetCalendarClass(); var months = [. "Jan"=0, "Feb"=1, "Mar"=2, "Apr"=3, "May"=4, "Jun"=5, "Jul"=6, "Aug"=7, "Sep"=8, "Oct"=9, "Nov"=10, "Dec" = 11 .]; var MONTH = 2; var DAYOFMONTH = 5; var YEAR = 1; var HOUROFDAY = 11; var MINUTE = 12; var SECOND = 13; c.set(YEAR, ToInt(m[3])); c.set(MONTH, months[m[2]]); c.set(DAYOFMONTH, ToInt(m[1])); c.set(HOUROFDAY, ToInt(m[4])); c.set(MINUTE, ToInt(m[5])); c.set(SECOND, ToInt(m[6])); return c; end; var GetMillis = fun(s) var c = GetTimeObj(s); return c.getTimeInMillis(); end; var GetDay = fun(s) // Fri, 5 Jul 2019 10:31:35 +0000 var m = Str_Match(s, `\w+, (\d+) (\w+) (\d+) (\d+)\:(\d+)\:(\d+) \+0000`); return ToString(m[2]) + ToString(m[1]) + "-" + ToString(m[3]) end; var formatDate = fun(c) var YEAR = 1; var DAY = 5; var MONTH = 2; return ToString(c.get(MONTH)+1) + "-" + ToString(c.get(DAY)) + "-" + ToString(c.get(YEAR)) end; var formatDuration = fun(minutes) var days = minutes div (60 * 24); var rest = minutes mod (60 * 24); var hours = rest div 60; return ToString(days) + " days " + ToString(hours) + " hours" end; var TestTitle = fun(title) var res = false; var tests = [ "danieltest", "proddtest", "deployment", "externalteam", "[CAP-1]", "[CAP-250]", "teamkelly", "vivqa" ]; every t in tests do if Str_IndexOf(t, title) >= 0 then res = true end end; return res end; var ParseReviews = fun() if (url == "latest" or url == "test") then // url = "http://adam.cheyer.com/Bixby/SearchRequest-july.xml" url = "http://www.adam.cheyer.com/Bixby/SearchRequest-all.xml" end; var P = GetURL(url, nil, nil, [. mimetype="text/xml" .]) ? nil; var res = []; if (P != nil) then every item in Elem(P, "item") do var ok = true; var title = GetField(P, "title", item); if (title != nil) and !TestTitle(title) then var elt = [. .]; var f = Str_Match(title, `\[CAP-(\d+)\] (\w+).(\w+)\@(\d+.\d+.\d+)`); if f == nil then elt.nomatch := title; ok = false else elt.name :=f[2] + "." + f[3]; elt.version := f[4] end; var c = GetMillis(GetField(P, "created", item)); var u = GetMillis(GetField(P, "updated", item)); elt.status := GetField(P, "status", item); elt.resolution := GetField(P, "resolution", item); elt.assignee := GetField(P, "assignee", item); elt.created := c div 1000 div 60; // in minutes elt.updated := u div 1000 div 60; // in minutes elt.dateCreated := GetDay(GetField(P, "created", item)); elt.dateUpdated := GetDay(GetField(P, "updated", item)); if u > maxTime then maxTime = u; endTimeStr = GetField(P, "updated", item); endTimeC = GetTimeObj(endTimeStr); if minTime < 10 then minTime = u; end; end; if c < minTime then minTime = c; startTimeStr = GetField(P, "created", item); startTimeC = GetTimeObj(startTimeStr); end; if ok then res = res + [ elt ] end // else //res = res + [ "Error: " + title ] end end; // every end; return res end; var GetStatus = fun(info, reviews) var completed = 0; var inProgress = 0; var requested = 0; var manager = 0; var err = ""; every r in reviews do if r.status == "Review Completed" then completed = completed + 1 elsif r.status == "Review In Progress" then inProgress = inProgress + 1 elsif r.status == "Review Requested" then requested = requested + 1 elsif r.status == "Manager Review" then manager = manager + 1 else err = err + "|status:" + r.status end end; info.total := Size(reviews); info.completed := completed; info.inProgress := inProgress; info.requested := requested; info.manager := manager; // info.err := err; end; var GetTimes = fun(info, reviews, weekly) var t; var longestCompleted = 0; var timeCompleted = 0; var numCompleted = 0; var issueCompleted; var longestInProgress = 0; var timeInProgress = 0; var numInProgress = 0; var issueInProgress; var longestWaiting = 0; var timeWaiting = 0; var numWaiting = 0; var issueWaiting; var longestManager = 0; var timeManager = 0; var numManager = 0; var issueManager; var timeRejected = 0; var numRejected = 0; var longestRejected = 0; var issueRejected; var timeApproved = 0; var numApproved = 0; var longestApproved = 0; var issueApproved; var c = 0; var createdPerDay = [. .]; var resolvedPerDay = [. .]; every r in reviews do var c = createdPerDay[r.dateCreated] ? 0; c = c + 1; createdPerDay[r.dateCreated] := c; if r.status == "Review Completed" then var c = resolvedPerDay[r.dateCreated] ? 0; c = c + 1; resolvedPerDay[r.dateCreated] := c; t = r.updated - r.created; if t > longestCompleted then longestCompleted = t; issueCompleted = r.name + " v" + r.version ? r.nomatch end; timeCompleted = timeCompleted + t; numCompleted = numCompleted + 1; if r.resolution == "Rejected" then timeRejected = timeRejected + t; numRejected = numRejected + 1; if t > longestRejected then longestRejected = t; issueRejected = r.name + " v" + r.version ? r.nomatch end; else timeApproved = timeApproved + t; numApproved = numApproved + 1; if t > longestApproved then longestApproved = t; issueApproved = r.name + " v" + r.version ? r.nomatch end; end elsif r.status == "Review In Progress" then t = r.updated - r.created; if t > longestInProgress then longestInProgress = t; issueInProgress = r.name + " v" + r.version ? r.nomatch end; timeInProgress = timeInProgress + t; numInProgress = numInProgress + 1 elsif r.status == "Review Requested" then t = r.updated - r.created; if t > longestWaiting then longestWaiting = t; issueWaiting = r.name + " v" + r.version ? r.nomatch end; timeWaiting = timeWaiting + t; numWaiting = numWaiting + 1 elsif r.status == "Manager Review" then t = r.updated - r.created; if t > longestManager then longestManager = t; issueManager = r.name + " v" + r.version ? r.nomatch end; timeManager = timeManager + t; numManager = numManager + 1 end end; if weekly then if (numCompleted > 0) then info.averageCompletedHours := (timeCompleted div numCompleted) div 60; // in hours else info.averageCompletedHours := 0; end; if (numRejected > 0) then info.averageRejectedHours := (timeRejected div numRejected) div 60; else info.averageRejectedHours := 0; end; if (numApproved > 0) then info.averageApprovedHours := (timeApproved div numApproved) div 60; else info.averageApprovedHours := 0; end; else info.longestCompleted := formatDuration(longestCompleted); info.longestCompletedIssue := issueCompleted; if (numCompleted > 0) then info.averageCompleted := formatDuration(timeCompleted div numCompleted); else info.averageCompleted := -1; end; info.longestRejected := formatDuration(longestRejected); info.longestRejectedIssue := issueRejected; if (numRejected > 0) then info.averageRejected := formatDuration(timeRejected div numRejected); else info.averageRejected := -1; end; info.longestApproved := formatDuration(longestApproved); info.longestApprovedIssue := issueApproved; if (numApproved > 0) then info.averageApproved := formatDuration(timeApproved div numApproved); else info.averageApproved := -1; end; info.longestInProgress := formatDuration(longestInProgress); info.longestInProgressIssue := issueInProgress; if (numInProgress > 0) then info.averageInProgress := formatDuration(timeInProgress div numInProgress); else info.averageInProgress := -1; end; info.longestWaiting := formatDuration(longestWaiting); info.longestWaitingIssue := issueWaiting; if (numWaiting > 0) then info.averageWaiting := formatDuration(timeWaiting div numWaiting); else info.averageWaiting := -1; end; info.longestManager := formatDuration(longestManager); info.longestManagerIssue := issueManager; if (numManager > 0) then info.averageManager := formatDuration(timeManager div numManager); else info.averageManager := -1; end; end; c = 0; every cpd in createdPerDay do c = c + createdPerDay[cpd] end; if (Size(ToList(createdPerDay)) > 0) then info.averageCreatedPerDay := (c * 100 div Size(ToList(createdPerDay))) / 100; else info.averageCreatedPerDay := -1 end; info.totalCreatedIssues := c; c = 0; every rpd in resolvedPerDay do c = c + resolvedPerDay[rpd] end; if (Size(ToList(resolvedPerDay)) > 0) then info.averageResolvedPerDay := (c * 100 div Size(ToList(resolvedPerDay))) / 100; else info.averageResolvedPerDay := -1 end; info.totalResolvedIssues := c; info.numReviews := Size(reviews) end; var GetByName = fun(info, reviews) var byName = [. .]; var newByStatus = [. .]; var newCapsules = 0; every r in reviews do var name = (r.name ? "null"); if (name != "null") then var s = (newByStatus[r.status] ? {}); var s2 = s; s = s + { r.name }; newByStatus[r.status] := s; if (Size(s) > Size(s2)) then newCapsules = newCapsules + 1 end; if (r.status == "Review Completed") then var issues = (byName[name] ? []); issues = [ r ] + issues; byName[name] := issues end end end; newByStatus["total"] := newCapsules; return [. byName = byName, newByStatus = newByStatus .] end; var GetRejections = fun(info, reviews) var bn = GetByName(info, reviews); var byName = bn.byName; var newByStatus = bn.newByStatus; var totApproved = 0; var totApprovedVersions = 0; var totRejectedVersions = 0; var rejectedUntilApproved = 0; var longestTurns = -1; var longest; every name in byName do var rej = 0; var approved = false; every r in byName[name] do if r.resolution == "Rejected" then rej = rej + 1; totRejectedVersions = totRejectedVersions + 1; elsif r.resolution == "Approved" then if rej > longestTurns then longestTurns = rej; longest = byName[name]; end; rejectedUntilApproved = rejectedUntilApproved + rej; totApprovedVersions = totApprovedVersions + 1; approved = true; rej = 0 end; end; if approved then totApproved = totApproved + 1 end end; info.newCapsules := newByStatus["total"] ? 0; info.newRequested := newByStatus["Review Requested"] ? {}; info.newInProgress := newByStatus["Review In Progress"] ? {}; info.newManager := newByStatus["Manager Review"] ? {}; info.newCompleted := newByStatus["Review Completed"] ? {}; info.averageTurnsToApproval := ((rejectedUntilApproved + totApprovedVersions) * 100 div totApprovedVersions) / 100; info.totRejectedVersions := totRejectedVersions; info.rejectedUntilApproved := rejectedUntilApproved; info.totApprovedVersions := totApprovedVersions; info.totApproved := totApproved; info.longestTurnsToApproval := longest; info.longestTurns := longestTurns + 1; // info.byName := byName end; var GetWeeklyStats = fun(info, reviews) var DAYOFWEEK = 7; var WEEKOFYEAR = 3; var startPeriod = startTimeC.clone(); startPeriod.set(DAYOFWEEK, 1); var weekly = [. .]; while startPeriod.getTimeInMillis() < endTimeC.getTimeInMillis() do var info2 = [. .]; var endPeriod = startPeriod.clone(); endPeriod.set(WEEKOFYEAR, endPeriod.get(WEEKOFYEAR)+1); var slice = GetTimeSlice(reviews, startPeriod.getTimeInMillis() div 1000 div 60, endPeriod.getTimeInMillis() div 1000 div 60); GetStatus(info2, slice); GetTimes(info2, slice, true); // GetRejections(info2, slice); weekly[formatDate(startPeriod)] := info2; startPeriod = endPeriod.clone(); end; info.weekly := weekly end; var reviews = ParseReviews(); var teams = SplitByTeam(reviews); var res = [. startTime = startTimeStr, endTime = endTimeStr .]; every team in teams do var info = [. .]; GetStatus(info, teams[team]); GetTimes(info, teams[team], false); GetRejections(info, teams[team]); GetWeeklyStats(info, teams[team]); res[team] := info; end; res;