private int AddSectionCommitsForFile(ExcelWorksheet sheet, FileStat fileChange, int rowCounter) { sheet.Cells[rowCounter, 1].Value = fileChange.Filename; sheet.Cells[rowCounter, 1].Style.Font.Size = 16; rowCounter++; sheet.Cells[rowCounter, 1].Value = "Latest commit"; sheet.Cells[rowCounter, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; sheet.Cells[rowCounter, 2].Value = fileChange.LatestCommit; rowCounter++; sheet.Cells[rowCounter, 1].Value = "Commits"; sheet.Cells[rowCounter, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; sheet.Cells[rowCounter, 2].Value = fileChange.CommitCount; rowCounter++; if (fileChange.FileExists) { var linesOfCode = fileChange.LinesOfCode > 0 ? fileChange.LinesOfCode.ToString() : "N/A"; sheet.Cells[rowCounter, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; sheet.Cells[rowCounter, 2].Value = linesOfCode; rowCounter++; var cyclomaticComplexity = fileChange.CyclomaticComplexity > 0 ? fileChange.CyclomaticComplexity.ToString() : "N/A"; sheet.Cells[rowCounter, 1].Value = "Cyclomatic complexity"; sheet.Cells[rowCounter, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; sheet.Cells[rowCounter, 2].Value = cyclomaticComplexity; rowCounter++; var methodCount = fileChange.MethodCount > 0 ? fileChange.MethodCount.ToString() : "N/A"; sheet.Cells[rowCounter, 1].Value = "Lines of code"; sheet.Cells[rowCounter, 1].Value = "Method count"; sheet.Cells[rowCounter, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; sheet.Cells[rowCounter, 2].Value = methodCount; rowCounter++; } else { sheet.Cells[rowCounter, 1].Value = "File has been deleted"; sheet.Cells[rowCounter, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; rowCounter++; } TableHeader(sheet, rowCounter, 1, "Author", 25); TableHeader(sheet, rowCounter, 2, "Commits", 9); TableHeader(sheet, rowCounter, 3, "Percentage", 11); TableHeader(sheet, rowCounter, 4, "Latest commit", 11); rowCounter++; foreach (var userfileChange in UserfileCommitsList.Where(ufc => ufc.Filename == fileChange.Filename)) { sheet.Cells[rowCounter, 1].Value = userfileChange.Username; sheet.Cells[rowCounter, 2].Value = userfileChange.CommitCount; sheet.Cells[rowCounter, 3].Value = (double)userfileChange.CommitCount / (double)fileChange.CommitCount; sheet.Cells[rowCounter, 3].Style.Numberformat.Format = "#,##0.00%"; var commitDatesOrdered = userfileChange.CommitDates.OrderBy(date => date); sheet.Cells[rowCounter, 4].Value = commitDatesOrdered.Last().ToString("yyyy-MM-dd"); rowCounter++; } return(rowCounter); }
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(StringBuilder sb, FileStat fileChange, int sectionCounter) { sb.AppendLine("<div class=\"row\"><div class=\"col-md-6\">"); sb.AppendLine($"<h3>{WebUtility.HtmlEncode(fileChange.Filename)}</h3>"); sb.AppendLine("<table class=\"table pull-left\" style=\"width: 500px\">"); sb.AppendLine($"<tr><td class=\"text-right\">Latest commit</td><td>{fileChange.LatestCommit.ToString("yyyy-MM-dd")}</td></tr>"); sb.AppendLine($"<tr><td class=\"text-right\">Commits</td><td>{fileChange.CommitCount}</td></tr>"); 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"; sb.AppendLine($"<tr><td class=\"text-right\">Lines of code</td><td>{linesOfCode}</td></tr>"); sb.AppendLine($"<tr><td class=\"text-right\">Cyclomatic Complexity</td><td>{cyclomaticComplexity}</td></tr>"); sb.AppendLine($"<tr><td class=\"text-right\">Method count</td><td>{methodCount}</td></tr>"); } else { sb.AppendLine($"<tr><td class=\"text-right\">File has been deleted</td><td></td></tr>"); } sb.AppendLine("</table>"); sb.AppendLine("</div>"); sb.AppendLine("<div class=\"col-md-6\">"); sb.AppendLine("</div>"); sb.AppendLine("</div>"); sb.AppendLine("<div class=\"row\"><div class=\"col-md-6\">"); sb.AppendLine("<table class=\"table pull-left\" style=\"width: 500px\">"); sb.AppendLine($"<tr><th>Name</th><th>Commits</th><th>Percentage</th><th>Latest commit</th></tr>"); var commitDates = new List <ScatterPoint>(); foreach (var userfileChange in UserfileCommitsList.Where(ufc => ufc.Filename == fileChange.Filename)) { var username = WebUtility.HtmlEncode(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); var latestCommit = GenerateScatterPlotData(commitDates, userfileChange); sb.AppendLine($"<tr><td class=\"text-right\">{username}</td><td>{changeCount}</td><td>{percentage}%</td><td>{latestCommit}</td></tr>"); } sb.AppendLine("</table>"); sb.AppendLine("</div>"); sb.AppendLine("<div class=\"col-md-6\">"); AddScatterplotJavascript(sb, commitDates, sectionCounter); sb.AppendLine($" <div id=\"scatterChart{sectionCounter}\" class=\"spinner\"></div>"); sb.AppendLine("</div>"); sb.AppendLine("</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()); }