private void AddSectionCommitsForEachMonth(ExcelWorksheet sheet) { Header(sheet, "Commits for each sub-folder"); int rowCounter = 3; TableHeader(sheet, rowCounter, 1, "Folder", 40); sheet.Column(1).Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; TableHeader(sheet, rowCounter, 2, "File changes", 13); sheet.Column(2).Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; TableHeader(sheet, rowCounter, 3, "Percentage", 10); sheet.Column(3).Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; sheet.Column(3).Style.Numberformat.Format = "#,##0.00%"; rowCounter++; var totalCommits = FileCommitsList.Sum(fc => fc.CommitCount); foreach (var folder in FolderCommitsList.Take(25)) { sheet.Cells[rowCounter, 1].Value = folder.FolderName; sheet.Cells[rowCounter, 2].Value = FolderCommits[folder.FolderName].FileChanges; var percentage = (double)FolderCommits[folder.FolderName].FileChanges / (double)totalCommits; sheet.Cells[rowCounter, 3].Value = percentage; rowCounter++; } var chart = sheet.Drawings.AddChart("Commits each day", OfficeOpenXml.Drawing.Chart.eChartType.Pie); chart.SetSize(500, 500); chart.SetPosition(0, 450); var series1 = chart.Series.Add($"$B$4:$B${rowCounter}", $"$A$4:$A${rowCounter}"); }
private void AddSectionStatistics(ExcelWorksheet sheet, Analysis analysis) { Header(sheet, "Statistics"); sheet.Column(1).Width = 24; sheet.Column(1).Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; sheet.Column(2).Width = 11; sheet.Column(2).Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; int rowCounter = 3; sheet.Cells[rowCounter, 1].Value = "First commit"; sheet.Cells[rowCounter, 2].Value = analysis.FirstCommitDate.ToString("yyyy-MM-dd"); rowCounter++; sheet.Cells[rowCounter, 1].Value = "Latest commit"; sheet.Cells[rowCounter, 2].Value = analysis.LatestCommitDate.ToString("yyyy-MM-dd"); rowCounter++; var totalCommits = FileCommitsList.Sum(fc => fc.CommitCount); sheet.Cells[rowCounter, 1].Value = "Number of commits"; sheet.Cells[rowCounter, 2].Value = totalCommits; rowCounter++; sheet.Cells[rowCounter, 1].Value = "Lines of code analyzed"; sheet.Cells[rowCounter, 2].Value = analysis.LinesOfCodeanalyzed; rowCounter++; var numberOfAuthors = UserfileCommitsList.Select(ufc => ufc.Username).Distinct().Count(); sheet.Cells[rowCounter, 1].Value = "Number of authors"; sheet.Cells[rowCounter, 2].Value = numberOfAuthors; rowCounter++; sheet.Cells[rowCounter, 1].Value = "Analysis time(milliseconds)"; sheet.Cells[rowCounter, 2].Value = analysis.AnalysisTime; rowCounter++; }
private void AddSectionCommitsForEachFolder(StringBuilder sb) { var totalCommits = FileCommitsList.Sum(fc => fc.CommitCount); sb.AppendLine("<div class=\"row\">"); sb.AppendLine("<div class=\"col-md-6\">"); sb.AppendLine("<h2>Commits for each sub-folder</h2>"); sb.AppendLine("<table class=\"table pull-left\" style=\"width: 500px\">"); sb.AppendLine("<tr><th class=\"text-right\">Folder</th><th class=\"text-right\">File changes</th><th></th></tr>"); int folderCounter = 1; foreach (var folder in FolderCommitsList.Take(25)) { var changeCount = string.Format("{0,5}", FolderCommits[folder.FolderName].FileChanges); var percentage = string.Format("{0,5:#0.0}", ((double)FolderCommits[folder.FolderName].FileChanges / (double)totalCommits) * 100); var expand = folder.Children.Keys.Count > 0 ? $"<span onclick=\"expandFolder({folderCounter})\" id=\"folderSpanExpand{folderCounter}\" class=\"treeViewCaret\">Expand</span>" : ""; sb.AppendLine($"<tr><td class=\"text-right\">{WebUtility.HtmlEncode(folder.FolderName)}</td><td class=\"text-right text-nowrap\">{changeCount} ({percentage}%)</td><td>{expand}</td></tr>"); if (folder.Children.Keys.Count > 0) { sb.AppendLine($"<tr id=\"folderTrExpand{folderCounter}\" class=\"nested\"><td colspan=\"3\" style=\"overflow: scroll\">"); sb.AppendLine($"<ul id=\"folderUlExpand{folderCounter}\" class=\"nested\">"); AddSectionCommitsForEachFolderChildren(sb, folder, 0); sb.AppendLine("</ul>"); sb.AppendLine("</td></tr>"); } folderCounter++; } var total = string.Format("{0,5}", totalCommits); sb.AppendLine($"<tr><td class=\"text-right\">Total number of Commits analyzed</td><td class=\"text-right\">{total} ({string.Format("{0,5:##0.0}", 100)}%)</td></td></tr>"); sb.AppendLine("</table>\n"); sb.AppendLine("</div>"); sb.AppendLine("<div class=\"col-md-6\">"); AddPieChartJavascript(sb); sb.AppendLine("<div id=\"piechart\" style=\"width: 48px; height: 48px;\" class=\"spinner\"></div>"); sb.AppendLine("<script type=\"text/javascript\">"); sb.AppendLine("var toggler = document.getElementsByClassName(\"treeViewCaret\");"); sb.AppendLine("var i;"); sb.AppendLine("for (i = 0; i < toggler.length; i++) {"); sb.AppendLine(" toggler[i].addEventListener(\"click\", function() {"); sb.AppendLine(" var children = this.parentElement.querySelector(\".nested\");"); sb.AppendLine(" if(children) {"); sb.AppendLine(" children.classList.toggle(\"active\");"); sb.AppendLine(" this.classList.toggle(\"caret-down\");"); sb.AppendLine(" }"); sb.AppendLine(" });"); sb.AppendLine("}"); sb.AppendLine("function expandFolder(folderId) {"); sb.AppendLine(" var folderExpander = document.getElementById('folderTrExpand' + folderId);"); sb.AppendLine(" folderExpander.classList.toggle('active');"); sb.AppendLine(" folderExpander = document.getElementById('folderUlExpand' + folderId);"); sb.AppendLine(" folderExpander.classList.toggle('active');"); sb.AppendLine(" folderExpander = document.getElementById('folderSpanExpand' + folderId)"); sb.AppendLine(" folderExpander.classList.toggle('caret-down');"); sb.AppendLine("}"); sb.AppendLine("</script>"); sb.AppendLine("</div></div>"); }
public void Generate(Analysis analysis) { Console.WriteLine("Generating Text file report..."); StringBuilder sb = new StringBuilder(); FileCommitsList = analysis.FileCommits.Values.OrderByDescending(fc => fc.CommitCount).ThenBy(fc => fc.Filename); UserfileCommitsList = analysis.UserfileCommits.Values.OrderByDescending(fc => fc.CommitCount).ThenBy(fc => fc.Filename).ThenBy(fc => fc.Username); var totalCommits = FileCommitsList.Sum(fc => fc.CommitCount); var numberOfAuthors = UserfileCommitsList.Select(ufc => ufc.Username).Distinct().Count(); sb.AppendLine($"{Title}\n"); sb.AppendLine($"Report created: {analysis.CreatedDate.ToString("yyyy-MM-dd")}"); sb.AppendLine($"First commit: {analysis.FirstCommitDate.ToString("yyyy-MM-dd")}"); sb.AppendLine($"Latest commit: {analysis.LatestCommitDate.ToString("yyyy-MM-dd")}"); sb.AppendLine($"Number of commits: {totalCommits}"); sb.AppendLine($"Lines of code analyzed: {analysis.LinesOfCodeanalyzed}"); sb.AppendLine($"Number of authors: {numberOfAuthors}"); sb.AppendLine($"Analysis time(milliseconds): {analysis.AnalysisTime}"); sb.AppendLine(); var folderCommitsList = analysis.FolderCommits.Values.OrderByDescending(fc => fc.FileChanges); foreach (var folder in folderCommitsList.Take(NumberOfFilesToList)) { var folderName = string.Format("{0,50}", folder.FolderName); var changeCount = string.Format("{0,5}", analysis.FolderCommits[folder.FolderName].FileChanges); var percentage = string.Format("{0,5:#0.00}", ((double)analysis.FolderCommits[folder.FolderName].FileChanges / (double)totalCommits) * 100); sb.AppendLine($"{folderName}: {changeCount} ({percentage}%)"); } foreach (var fileChange in FileCommitsList.Take(50)) { sb.AppendLine(""); string fileInfo = "File has been deleted"; if (fileChange.FileExists) { var linesOfCode = fileChange.LinesOfCode > 0 ? fileChange.LinesOfCode.ToString() : "N/A"; var cyclomaticComplexity = fileChange.CyclomaticComplexity > 0 ? fileChange.CyclomaticComplexity.ToString() : "N/A"; var methodCount = fileChange.MethodCount > 0 ? fileChange.MethodCount.ToString() : "N/A"; fileInfo = $"Lines of code: {linesOfCode} - Cyclomatic Complexity: {cyclomaticComplexity} - Method count: {methodCount}"; } sb.AppendLine($"{fileChange.Filename}: {fileChange.CommitCount} - Latest commit: {fileChange.LatestCommit.ToString("yyyy-MM-dd")} - {fileInfo}\n"); foreach (var userfileChange in UserfileCommitsList.Where(ufc => ufc.Filename == fileChange.Filename)) { var username = string.Format("{0,20}", userfileChange.Username); var changeCount = string.Format("{0,3}", userfileChange.CommitCount); var percentage = string.Format("{0,5:#0.00}", ((double)userfileChange.CommitCount / (double)fileChange.CommitCount) * 100); sb.AppendLine($" {username}: {changeCount} ({percentage}%)"); } } SystemIO.WriteAllText($"{ReportFilename}.txt", sb.ToString()); }
private void AddSectionCommitsForEachFile(ExcelWorksheet sheet) { Header(sheet, $"Top {NumberOfFilesToList} most changed files"); int rowCounter = 3; foreach (var fileChange in FileCommitsList.Take(NumberOfFilesToList)) { rowCounter = AddSectionCommitsForFile(sheet, fileChange, rowCounter); } }
public void Generate(Analysis analysis) { Console.WriteLine("Generating HTML report..."); if (analysis == null) { throw new ArgumentException("Parameter analysis is null.", nameof(analysis)); } this.FileCommitsList = analysis.FileCommits.Values.OrderByDescending(fc => fc.CommitCount).ThenBy(fc => fc.Filename); this.UserfileCommitsList = analysis.UserfileCommits.Values.OrderByDescending(fc => fc.CommitCount).ThenBy(fc => fc.Filename).ThenBy(fc => fc.Username); var key = 1; foreach (var username in analysis.UserfileCommits.Values.Select(fc => fc.Username).Distinct().OrderBy(un => un)) { UserNameKey.Add(username, key++); } ; this.FolderCommits = analysis.FolderCommits; this.FolderCommitsList = analysis.FolderCommits.Values.OrderByDescending(fc => fc.FileChanges); StringBuilder sb = new StringBuilder(); AddHeader(sb, analysis); AddNavTabs(sb); sb.AppendLine("<div class=\"tab-content\">"); sb.AppendLine("<div role=\"tabpanel\" class=\"tab-pane active\" id=\"commitsForEachSubfolder\">"); AddSectionCommitsForEachFolder(sb); sb.Append($"<h2 id=\"mostChangedFiles\">Top {NumberOfFilesToList} most changed files</h2>"); var sectionCounter = 1; foreach (var fileChange in FileCommitsList.Take(NumberOfFilesToList)) { AddSectionCommitsForEachFile(sb, fileChange, sectionCounter++); } sb.AppendLine("</div>"); sb.AppendLine("<div role=\"tabpanel\" class=\"tab-pane\" id=\"projectStatistics\">"); AddSectionProjectStatistics(sb, analysis); AddSectionCommitsForEachDay(sb, analysis.CommitsEachDay); AddSectionLinesChangedEachDay(sb, analysis.LinesOfCodeAddedEachDay, analysis.LinesOfCodeDeletedEachDay); AddSectionCodeAge(sb, analysis.CodeAge); if (analysis.Tags.Any()) { AddSectionTags(sb, analysis.Tags); } if (analysis.Branches.Any()) { AddSectionBranches(sb, analysis.Branches); } AddSectionFileTypes(sb, analysis.FileTypes); sb.AppendLine("</div>"); sb.AppendLine("</div>"); AddFooter(sb); SystemIO.WriteAllText($"{ReportFilename}.html", sb.ToString()); }
private void AddSectionProjectStatistics(StringBuilder sb, Analysis analysis) { var totalCommits = FileCommitsList.Sum(fc => fc.CommitCount); var numberOfAuthors = UserfileCommitsList.Select(ufc => ufc.Username).Distinct().Count(); sb.AppendLine("<div class=\"row\">"); sb.AppendLine("<div class=\"col\">"); sb.AppendLine("<table class=\"table pull-left\" style=\"width: 500px\">"); sb.AppendLine($"<tr><td class=\"text-right\">First commit</td><td class=\"text-right\">{analysis.FirstCommitDate.ToString("yyyy-MM-dd")}</td></tr>"); sb.AppendLine($"<tr><td class=\"text-right\">Latest commit</td><td class=\"text-right\">{analysis.LatestCommitDate.ToString("yyyy-MM-dd")}</td></tr>"); sb.AppendLine($"<tr><td class=\"text-right\">Number of commits</td><td class=\"text-right\">{totalCommits}</td></tr>"); sb.AppendLine($"<tr><td class=\"text-right\">Lines of code analyzed</td><td class=\"text-right\">{analysis.LinesOfCodeanalyzed}</td></tr>"); sb.AppendLine($"<tr><td class=\"text-right\">Number of authors</td><td class=\"text-right\">{numberOfAuthors}</td></tr>"); sb.AppendLine($"<tr><td class=\"text-right\">Analysis time(milliseconds)</td><td class=\"text-right\">{analysis.AnalysisTime}</td></tr>"); sb.AppendLine("</table>"); sb.AppendLine("</div></div>"); }
public void Generate(Analysis analysis) { Console.WriteLine("Generating Markdown report..."); StringBuilder sb = new StringBuilder(); FileCommitsList = analysis.FileCommits.Values.OrderByDescending(fc => fc.CommitCount).ThenBy(fc => fc.Filename); UserfileCommitsList = analysis.UserfileCommits.Values.OrderByDescending(fc => fc.CommitCount).ThenBy(fc => fc.Filename).ThenBy(fc => fc.Username); sb.AppendLine($"# {Title}\n"); sb.AppendLine($"Report created: {analysis.CreatedDate.ToString("yyyy-MM-dd")}\n"); var totalCommits = FileCommitsList.Sum(fc => fc.CommitCount); var numberOfAuthors = UserfileCommitsList.Select(ufc => ufc.Username).Distinct().Count(); sb.AppendLine($"## Statistics\n"); sb.AppendLine("| | |"); sb.AppendLine("|---:|----:|"); sb.AppendLine($"| First commit | {analysis.FirstCommitDate.ToString("yyyy-MM-dd")} |"); sb.AppendLine($"| Latest commit | {analysis.LatestCommitDate.ToString("yyyy-MM-dd")} |"); sb.AppendLine($"| Number of commits | {totalCommits} |"); sb.AppendLine($"| Lines of code analyzed | {analysis.LinesOfCodeanalyzed} |"); sb.AppendLine($"| Number of authors | {numberOfAuthors} |"); sb.AppendLine($"| Analysis time(milliseconds) | {analysis.AnalysisTime} |"); sb.AppendLine(); sb.AppendLine("## File changes for each sub-folder"); var folderCommitsList = analysis.FolderCommits.Values.OrderByDescending(fc => fc.FileChanges); foreach (var folder in folderCommitsList.Take(NumberOfFilesToList)) { var folderName = string.Format("{0,50}", folder.FolderName); var changeCount = string.Format("{0,5}", analysis.FolderCommits[folder.FolderName].FileChanges); var percentage = string.Format("{0,5:#0.00}", ((double)analysis.FolderCommits[folder.FolderName].FileChanges / (double)totalCommits) * 100); sb.AppendLine($"{folderName}: {changeCount} ({percentage}%)"); } sb.AppendLine($"{string.Format("{0,51}", "---------------")} {string.Format("{0,6}", "-----")} {string.Format("{0,7}", "------")}"); var total = string.Format("{0,5}", totalCommits); sb.AppendLine($"{string.Format("{0,50}", "Total number of Commits analyzed")}: {total} ({string.Format("{0,5:##0.0}", 100)}%)\n"); sb.AppendLine("---\n"); foreach (var fileChange in FileCommitsList.Take(50)) { var linesOfCode = fileChange.LinesOfCode > 0 ? fileChange.LinesOfCode.ToString() : "N/A"; var cyclomaticComplexity = fileChange.CyclomaticComplexity > 0 ? fileChange.CyclomaticComplexity.ToString() : "N/A"; var methodCount = fileChange.MethodCount > 0 ? fileChange.MethodCount.ToString() : "N/A"; sb.AppendLine($"### {fileChange.Filename}\n"); sb.AppendLine("| | |"); sb.AppendLine("|---:|----:|"); sb.AppendLine($"| Latest commit | {fileChange.LatestCommit.ToString("yyyy-MM-dd")} |"); sb.AppendLine($"| Commits | {fileChange.CommitCount} |"); if (fileChange.FileExists) { sb.AppendLine($"| Lines of code | {linesOfCode} |"); sb.AppendLine($"| Cyclomatic Complexity | {cyclomaticComplexity} |"); sb.AppendLine($"| Method count | {methodCount} |"); } else { sb.AppendLine($"| File has been deleted | |"); } sb.AppendLine(); sb.AppendLine("__Commits by user:__\n"); sb.AppendLine($"| Name | Commits | Percentage |"); sb.AppendLine($"|-----:|--------:|-----------:|"); foreach (var userfileChange in UserfileCommitsList.Where(ufc => ufc.Filename == fileChange.Filename)) { var username = string.Format("{0,20}", userfileChange.Username); var changeCount = string.Format("{0,3}", userfileChange.CommitCount); var percentage = string.Format("{0,5:#0.00}", ((double)userfileChange.CommitCount / (double)fileChange.CommitCount) * 100); sb.AppendLine($"| {username} | {changeCount} | {percentage}% |"); } sb.AppendLine(); } sb.AppendLine("## Code age\n"); sb.AppendLine("| Code age(months) | Filechanges |"); sb.AppendLine("|---:|---:|"); var maxAge = analysis.CodeAge.AsEnumerable().OrderByDescending(kvp => kvp.Key).First().Key; for (var month = 0; month <= maxAge; month++) { var fileChanges = analysis.CodeAge.ContainsKey(month) ? analysis.CodeAge[month] : 0; sb.AppendLine($"|{month}|{fileChanges}|"); } sb.AppendLine(); if (analysis.Tags.Any()) { var tagsOrdered = analysis.Tags.AsEnumerable().OrderByDescending(kvp => kvp.Key).ThenBy(kvp => kvp.Value); sb.AppendLine("## Tags\n"); sb.AppendLine("| Name | Date |"); sb.AppendLine("|:---|----:|"); foreach (var kvp in tagsOrdered) { sb.AppendLine($"| {kvp.Value} | {kvp.Key.ToString("yyyy-MM-dd")} |"); } sb.AppendLine(); } if (analysis.Branches.Any()) { sb.AppendLine("## Branches\n"); sb.AppendLine("| Name |"); sb.AppendLine("|:---|"); foreach (var branch in analysis.Branches) { sb.AppendLine($"| {branch} |"); } sb.AppendLine(); } var fileTypesOrdered = analysis.FileTypes.AsEnumerable().OrderByDescending(kvp => kvp.Value).ThenBy(kvp => kvp.Key); sb.AppendLine("## Number of files of each type\n"); sb.AppendLine("| File type | Count |"); sb.AppendLine("|---:|----:|"); foreach (var kvp in fileTypesOrdered) { sb.AppendLine($"| {kvp.Key} | {kvp.Value} |"); } SystemIO.WriteAllText($"{ReportFilename}.md", sb.ToString()); }