Checkpoint

This commit is contained in:
Matt Soucy 2020-07-03 17:50:47 -04:00
parent cabf35c16d
commit 2b4d799d4a
5 changed files with 166 additions and 83 deletions

View File

@ -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'
}

View File

@ -138,8 +138,9 @@ fun main(args: Array<String>) = 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<String>) = mainBody {
}
}
renderSummary(projectRootFile, summaryModel, outDir)
// Render summary
System.err.println("Done, summary is in ${outDir}/index.html")
}

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -7,45 +7,86 @@ import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
class SummaryModel(val db : Database) {
object ProjectTable : IntIdTable("projects", "projectid") {
private object ProjectTable : IntIdTable("projects", "projectid") {
val project = text("project").uniqueIndex("project_idx")
}
object DirsTable : IntIdTable("dirs", "dirid") {
}
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)
}
object FilesTable : IntIdTable("files", "fileid") {
}
private object FilesTable : IntIdTable("files", "fileid") {
val fname = text("fname")
val dirid = integer("dirid").index("filesdir_idx").references(DirsTable.id)
}
object LinesTable : IntIdTable("lines", "lineid") {
}
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)
}
object AuthorsTable : IntIdTable("authors", "authorid") {
}
private object AuthorsTable : IntIdTable("authors", "authorid") {
val author = text("author").uniqueIndex("authorstrs_idx")
}
object AuthorsGroupsTable : IntIdTable("authorgroups", "authorgroupid") {
}
private object AuthorsGroupsTable : IntIdTable("authorgroups", "authorgroupid") {
val authors = text("authorsstr").uniqueIndex("authorgroupsstrs_idx")
}
object AuthorsAuthorGroupsTable : Table("authors_authorgroups") {
}
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)
}
object AllocationsTable : IntIdTable("allocations", "allocationid") {
}
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)
}
}
class LineDict {
var stats = Statistics()
var authorRisks = mutableMapOf<String, Statistics>()
}
class FileTree {
var name = ""
var stats = Statistics()
var authorRisks = mutableMapOf<String, Statistics>()
var lines = mutableListOf<LineDict>()
}
class FileEntry(var name : String = "") {
var stats = Statistics()
var authorRisks = mutableMapOf<String, Statistics>()
}
class ProjectTree {
var name = "root"
var files = mutableMapOf<Int, FileEntry>()
var dirs = mutableListOf<Int>()
}
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<FileEntry>()
var dirs = mutableListOf<ProjectTreeNode>()
}
class ProjectTreeResult(var name : String, var root : ProjectTreeNode) {
var stats = Statistics()
var authorRisks = mutableMapOf<String, Statistics>()
}
class SummaryModel(val db : Database) {
val GIT_BY_A_BUS_BELOW_THRESHOLD = "Git by a Bus Safe Author"
@ -53,44 +94,6 @@ class SummaryModel(val db : Database) {
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<String, Statistics>()
}
class FileTree {
var name = ""
var stats = Statistics()
var authorRisks = mutableMapOf<String, Statistics>()
var lines = mutableListOf<LineDict>()
}
class FileEntry(var name : String) {
var stats = Statistics()
var authorRisks = mutableMapOf<String, Statistics>()
}
class ProjectTree {
var name = "root"
var files = mutableMapOf<Int, FileEntry>()
var dirs = mutableListOf<Int>()
}
class ProjectTreeNode {
var name = "root"
var files = mutableListOf<FileEntry>()
var dirs = mutableListOf<ProjectTreeNode>()
}
class ProjectTreeResult(var name : String, var root : ProjectTreeNode) {
var stats = Statistics()
var authorRisks = mutableMapOf<String, Statistics>()
}
class ProjectFilesResult(var fileId : Int, var fname : Path)
private val lineAllocations = (LinesTable leftJoin AllocationsTable)
private val lineAllocationGroups = (lineAllocations leftJoin AuthorsGroupsTable)
private val manyJoined = (lineAllocations leftJoin FilesTable leftJoin DirsTable)
@ -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)