From 2b4d799d4a64d9f2e427b73015aeba18d39630fc Mon Sep 17 00:00:00 2001 From: Matt Soucy Date: Fri, 3 Jul 2020 17:50:47 -0400 Subject: [PATCH] Checkpoint --- build.gradle | 2 + src/main/kotlin/me/msoucy/gbat/Main.kt | 7 +- src/main/kotlin/me/msoucy/gbat/Renderer.kt | 56 ++++++ .../me/msoucy/gbat/models/KnowledgeModel.kt | 1 - .../me/msoucy/gbat/models/SummaryModel.kt | 183 ++++++++++-------- 5 files changed, 166 insertions(+), 83 deletions(-) create mode 100644 src/main/kotlin/me/msoucy/gbat/Renderer.kt diff --git a/build.gradle b/build.gradle index e99ffa8..6c1e6ae 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { id 'org.jetbrains.kotlin.jvm' version "$kotlinVersion" + id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlinVersion" id 'application' } @@ -24,5 +25,6 @@ dependencies { implementation "org.jetbrains.exposed:exposed-dao:$kotlin_exposed_version" implementation "org.jetbrains.exposed:exposed-jdbc:$kotlin_exposed_version" implementation "org.xerial:sqlite-jdbc:3.30.1" + implementation 'com.google.code.gson:gson:2.8.6' testImplementation 'junit:junit:4.12' } diff --git a/src/main/kotlin/me/msoucy/gbat/Main.kt b/src/main/kotlin/me/msoucy/gbat/Main.kt index cde888a..d677689 100644 --- a/src/main/kotlin/me/msoucy/gbat/Main.kt +++ b/src/main/kotlin/me/msoucy/gbat/Main.kt @@ -138,8 +138,9 @@ fun main(args: Array) = mainBody { val dbFname = File(outDir, "summary.db") val summaryDb = Database.connect("jdbc:sqlite:${dbFname.absolutePath}", driver="org.sqlite.JDBC") transaction(summaryDb) { - exec("PRAGMA journal_mode = OFF") - exec("PRAGMA synchronous = OFF") + addLogger(StdOutSqlLogger) + // exec("PRAGMA journal_mode = OFF") + // exec("PRAGMA synchronous = OFF") } val summaryModel = SummaryModel(summaryDb) @@ -155,6 +156,8 @@ fun main(args: Array) = mainBody { } } + renderSummary(projectRootFile, summaryModel, outDir) + // Render summary System.err.println("Done, summary is in ${outDir}/index.html") } diff --git a/src/main/kotlin/me/msoucy/gbat/Renderer.kt b/src/main/kotlin/me/msoucy/gbat/Renderer.kt new file mode 100644 index 0000000..62ecb3c --- /dev/null +++ b/src/main/kotlin/me/msoucy/gbat/Renderer.kt @@ -0,0 +1,56 @@ +package me.msoucy.gbat + +import java.io.File + +import me.msoucy.gbat.models.ProjectTreeNode +import me.msoucy.gbat.models.ProjectTreeResult +import me.msoucy.gbat.models.Statistics +import me.msoucy.gbat.models.SummaryModel + +import com.google.gson.GsonBuilder +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.transactions.transaction + +val NUM_RISKIEST_AUTHORS = 10 +val NUM_RISKIEST_FILES = 10 + +class SummaryRenderer( + val summaryModel : SummaryModel, + val outputDir : File +) { + private val filesDir = File(outputDir, "files") + private val gson = GsonBuilder().setPrettyPrinting().create() + + fun renderAll(projectRoot : File) { + createFilesDir() + renderSummaryJson(projectRoot) + renderFileJson(projectRoot) + // renderSrc(projectRoot) + } + + private fun renderSummaryJson(projectRoot : File) { + val summary = summaryModel.projectSummary(projectRoot.absolutePath) + val json = gson.toJson(summary) + File(filesDir, "summary.json").writeText(json) + } + + private fun renderFileJson(projectRoot : File) { + summaryModel.projectFiles(projectRoot.absolutePath).forEach { + val json = gson.toJson(summaryModel.fileSummary(it.fileId)) + File(filesDir, "${it.fileId}.json").writeText(json) + } + } + + private fun createFilesDir() = filesDir.mkdirs() +} + +fun renderSummary( + projectRoot : File, + summaryModel : SummaryModel, + outputDir : File +) { + transaction(summaryModel.db) { + val renderer = SummaryRenderer(summaryModel, outputDir) + renderer.renderAll(projectRoot) + } +} \ No newline at end of file diff --git a/src/main/kotlin/me/msoucy/gbat/models/KnowledgeModel.kt b/src/main/kotlin/me/msoucy/gbat/models/KnowledgeModel.kt index 97dbd84..c9477ee 100644 --- a/src/main/kotlin/me/msoucy/gbat/models/KnowledgeModel.kt +++ b/src/main/kotlin/me/msoucy/gbat/models/KnowledgeModel.kt @@ -237,7 +237,6 @@ class KnowledgeModel(val db : Database, val constant : Double, val riskModel : R } private fun createTables() = transaction(db) { - println ("-- In create tables") SchemaUtils.dropDatabase() SchemaUtils.createMissingTablesAndColumns(AuthorsTable, KnowledgeAcctsTable, KnowledgeAuthorsTable, LineKnowledge) AuthorsTable.insertIgnore { diff --git a/src/main/kotlin/me/msoucy/gbat/models/SummaryModel.kt b/src/main/kotlin/me/msoucy/gbat/models/SummaryModel.kt index 0b810c3..d239242 100644 --- a/src/main/kotlin/me/msoucy/gbat/models/SummaryModel.kt +++ b/src/main/kotlin/me/msoucy/gbat/models/SummaryModel.kt @@ -7,89 +7,92 @@ import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.transaction -class SummaryModel(val db : Database) { +private object ProjectTable : IntIdTable("projects", "projectid") { + val project = text("project").uniqueIndex("project_idx") +} +private object DirsTable : IntIdTable("dirs", "dirid") { + val dir = text("dir") + val parentdirid = integer("parentdirid").references(DirsTable.id) + val projectid = integer("projectid").references(ProjectTable.id) + val dirsproj_idx = uniqueIndex("dirsproj_idx", dir, parentdirid, projectid) +} +private object FilesTable : IntIdTable("files", "fileid") { + val fname = text("fname") + val dirid = integer("dirid").index("filesdir_idx").references(DirsTable.id) +} +private object LinesTable : IntIdTable("lines", "lineid") { + val line = text("line") + val fileid = integer("fileid").index("linesfile_idx").references(FilesTable.id) + val linenum = integer("linenum") + val linesnumfile_idx = uniqueIndex("linesnumfile_idx", fileid, linenum) +} +private object AuthorsTable : IntIdTable("authors", "authorid") { + val author = text("author").uniqueIndex("authorstrs_idx") +} +private object AuthorsGroupsTable : IntIdTable("authorgroups", "authorgroupid") { + val authors = text("authorsstr").uniqueIndex("authorgroupsstrs_idx") +} +private object AuthorsAuthorGroupsTable : Table("authors_authorgroups") { + val authorid = integer("authorid").references(AuthorsTable.id) + val groupid = integer("authorgroupid").references(AuthorsGroupsTable.id) + override val primaryKey = PrimaryKey(authorid, groupid) +} +private object AllocationsTable : IntIdTable("allocations", "allocationid") { + val knowledge = double("knowledge") + val risk = double("risk") + val orphaned = double("orphaned") + val lineid = integer("lineid").index("linealloc_idx").references(LinesTable.id) + val authorgroupid = integer("authorgroupid").references(AuthorsGroupsTable.id) +} - object ProjectTable : IntIdTable("projects", "projectid") { - val project = text("project").uniqueIndex("project_idx") - } - object DirsTable : IntIdTable("dirs", "dirid") { - val dir = text("dir") - val parentdirid = integer("parentdirid").references(DirsTable.id) - val projectid = integer("projectid").references(ProjectTable.id) - val dirsproj_idx = uniqueIndex("dirsproj_idx", dir, parentdirid, projectid) - } - object FilesTable : IntIdTable("files", "fileid") { - val fname = text("fname") - val dirid = integer("dirid").index("filesdir_idx").references(DirsTable.id) - } - object LinesTable : IntIdTable("lines", "lineid") { - val line = text("line") - val fileid = integer("fileid").index("linesfile_idx").references(FilesTable.id) - val linenum = integer("linenum") - val linesnumfile_idx = uniqueIndex("linesnumfile_idx", fileid, linenum) - } - object AuthorsTable : IntIdTable("authors", "authorid") { - val author = text("author").uniqueIndex("authorstrs_idx") - } - object AuthorsGroupsTable : IntIdTable("authorgroups", "authorgroupid") { - val authors = text("authorsstr").uniqueIndex("authorgroupsstrs_idx") - } - object AuthorsAuthorGroupsTable : Table("authors_authorgroups") { - val authorid = integer("authorid").references(AuthorsTable.id) - val groupid = integer("authorgroupid").references(AuthorsGroupsTable.id) - override val primaryKey = PrimaryKey(authorid, groupid) - } - object AllocationsTable : IntIdTable("allocations", "allocationid") { - val knowledge = double("knowledge") - val risk = double("risk") - val orphaned = double("orphaned") - val lineid = integer("lineid").index("linealloc_idx").references(LinesTable.id) - val authorgroupid = integer("authorgroupid").references(AuthorsGroupsTable.id) - } +class LineDict { + var stats = Statistics() + var authorRisks = mutableMapOf() +} +class FileTree { + var name = "" + var stats = Statistics() + var authorRisks = mutableMapOf() + var lines = mutableListOf() +} +class FileEntry(var name : String = "") { + var stats = Statistics() + var authorRisks = mutableMapOf() +} +class ProjectTree { + var name = "root" + var files = mutableMapOf() + var dirs = mutableListOf() +} +class ProjectFilesResult(var fileId : Int, var fname : Path) + +data class Statistics( + var totKnowledge : Double = 0.0, + var totRisk : Double = 0.0, + var totOrphaned : Double = 0.0 +) { + constructor(row : ResultRow) : + this(row[AllocationsTable.knowledge.sum()] ?: 0.0, + row[AllocationsTable.risk.sum()] ?: 0.0, + row[AllocationsTable.orphaned.sum()] ?: 0.0) {} +} +class ProjectTreeNode { + var name = "root" + var files = mutableListOf() + var dirs = mutableListOf() +} +class ProjectTreeResult(var name : String, var root : ProjectTreeNode) { + var stats = Statistics() + var authorRisks = mutableMapOf() +} + +class SummaryModel(val db : Database) { val GIT_BY_A_BUS_BELOW_THRESHOLD = "Git by a Bus Safe Author" init { createTables() } - - data class Statistics(var totKnowledge : Double = 0.0, - var totRisk : Double = 0.0, - var totOrphaned : Double = 0.0) { - constructor(row : ResultRow) : - this(row[AllocationsTable.knowledge.sum()] ?: 0.0, - row[AllocationsTable.risk.sum()] ?: 0.0, - row[AllocationsTable.orphaned.sum()] ?: 0.0) {} - } - class LineDict { - var stats = Statistics() - var authorRisks = mutableMapOf() - } - class FileTree { - var name = "" - var stats = Statistics() - var authorRisks = mutableMapOf() - var lines = mutableListOf() - } - class FileEntry(var name : String) { - var stats = Statistics() - var authorRisks = mutableMapOf() - } - class ProjectTree { - var name = "root" - var files = mutableMapOf() - var dirs = mutableListOf() - } - class ProjectTreeNode { - var name = "root" - var files = mutableListOf() - var dirs = mutableListOf() - } - class ProjectTreeResult(var name : String, var root : ProjectTreeNode) { - var stats = Statistics() - var authorRisks = mutableMapOf() - } - class ProjectFilesResult(var fileId : Int, var fname : Path) private val lineAllocations = (LinesTable leftJoin AllocationsTable) private val lineAllocationGroups = (lineAllocations leftJoin AuthorsGroupsTable) @@ -204,7 +207,9 @@ class SummaryModel(val db : Database) { entry.value.files[row[FilesTable.id].value] = FileEntry(row[FilesTable.fname]) } entry.value.files.entries.forEach { (fileId, fileEntry) -> - lineAllocations.select { LinesTable.fileid eq fileId } + lineAllocations + .slice(AllocationsTable.knowledge.sum(), AllocationsTable.risk.sum(), AllocationsTable.orphaned.sum()) + .select { LinesTable.fileid eq fileId } .groupBy(LinesTable.fileid) .forEach { row -> fileEntry.stats.totKnowledge = row[AllocationsTable.knowledge.sum()] ?: 0.0 @@ -213,7 +218,13 @@ class SummaryModel(val db : Database) { } } entry.value.files.entries.forEach { (fileId, fileEntry) -> - lineAllocationGroups.select { LinesTable.fileid eq fileId } + lineAllocationGroups + .slice( + AllocationsTable.knowledge.sum(), + AllocationsTable.risk.sum(), + AllocationsTable.orphaned.sum(), + AuthorsGroupsTable.authors + ).select { LinesTable.fileid eq fileId } .groupBy(AllocationsTable.authorgroupid) .orderBy(AuthorsGroupsTable.authors) .forEach { row -> @@ -227,13 +238,25 @@ class SummaryModel(val db : Database) { val root = transformedRoot.dirs.first() val projectTree = ProjectTreeResult(project, root) - allJoined.select { DirsTable.projectid eq projectId } + allJoined + .slice( + AllocationsTable.knowledge.sum(), + AllocationsTable.risk.sum(), + AllocationsTable.orphaned.sum(), + AuthorsGroupsTable.authors + ) + .select { DirsTable.projectid eq projectId } .groupBy(AuthorsGroupsTable.id) .forEach { row -> projectTree.authorRisks[row[AuthorsGroupsTable.authors]] = Statistics(row) } - manyJoined.select { + manyJoined + .slice( + AllocationsTable.knowledge.sum(), + AllocationsTable.risk.sum(), + AllocationsTable.orphaned.sum() + ).select { DirsTable.projectid eq projectId }.first().let { row -> projectTree.stats = Statistics(row)