Checkpoint
This commit is contained in:
parent
cabf35c16d
commit
2b4d799d4a
@ -1,5 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'org.jetbrains.kotlin.jvm' version "$kotlinVersion"
|
id 'org.jetbrains.kotlin.jvm' version "$kotlinVersion"
|
||||||
|
id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlinVersion"
|
||||||
id 'application'
|
id 'application'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,5 +25,6 @@ dependencies {
|
|||||||
implementation "org.jetbrains.exposed:exposed-dao:$kotlin_exposed_version"
|
implementation "org.jetbrains.exposed:exposed-dao:$kotlin_exposed_version"
|
||||||
implementation "org.jetbrains.exposed:exposed-jdbc:$kotlin_exposed_version"
|
implementation "org.jetbrains.exposed:exposed-jdbc:$kotlin_exposed_version"
|
||||||
implementation "org.xerial:sqlite-jdbc:3.30.1"
|
implementation "org.xerial:sqlite-jdbc:3.30.1"
|
||||||
|
implementation 'com.google.code.gson:gson:2.8.6'
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
@ -138,8 +138,9 @@ fun main(args: Array<String>) = mainBody {
|
|||||||
val dbFname = File(outDir, "summary.db")
|
val dbFname = File(outDir, "summary.db")
|
||||||
val summaryDb = Database.connect("jdbc:sqlite:${dbFname.absolutePath}", driver="org.sqlite.JDBC")
|
val summaryDb = Database.connect("jdbc:sqlite:${dbFname.absolutePath}", driver="org.sqlite.JDBC")
|
||||||
transaction(summaryDb) {
|
transaction(summaryDb) {
|
||||||
exec("PRAGMA journal_mode = OFF")
|
addLogger(StdOutSqlLogger)
|
||||||
exec("PRAGMA synchronous = OFF")
|
// exec("PRAGMA journal_mode = OFF")
|
||||||
|
// exec("PRAGMA synchronous = OFF")
|
||||||
}
|
}
|
||||||
val summaryModel = SummaryModel(summaryDb)
|
val summaryModel = SummaryModel(summaryDb)
|
||||||
|
|
||||||
@ -155,6 +156,8 @@ fun main(args: Array<String>) = mainBody {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderSummary(projectRootFile, summaryModel, outDir)
|
||||||
|
|
||||||
// Render summary
|
// Render summary
|
||||||
System.err.println("Done, summary is in ${outDir}/index.html")
|
System.err.println("Done, summary is in ${outDir}/index.html")
|
||||||
}
|
}
|
||||||
|
56
src/main/kotlin/me/msoucy/gbat/Renderer.kt
Normal file
56
src/main/kotlin/me/msoucy/gbat/Renderer.kt
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@ -237,7 +237,6 @@ class KnowledgeModel(val db : Database, val constant : Double, val riskModel : R
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createTables() = transaction(db) {
|
private fun createTables() = transaction(db) {
|
||||||
println ("-- In create tables")
|
|
||||||
SchemaUtils.dropDatabase()
|
SchemaUtils.dropDatabase()
|
||||||
SchemaUtils.createMissingTablesAndColumns(AuthorsTable, KnowledgeAcctsTable, KnowledgeAuthorsTable, LineKnowledge)
|
SchemaUtils.createMissingTablesAndColumns(AuthorsTable, KnowledgeAcctsTable, KnowledgeAuthorsTable, LineKnowledge)
|
||||||
AuthorsTable.insertIgnore {
|
AuthorsTable.insertIgnore {
|
||||||
|
@ -7,89 +7,92 @@ import org.jetbrains.exposed.dao.id.IntIdTable
|
|||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
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") {
|
class LineDict {
|
||||||
val project = text("project").uniqueIndex("project_idx")
|
var stats = Statistics()
|
||||||
}
|
var authorRisks = mutableMapOf<String, Statistics>()
|
||||||
object DirsTable : IntIdTable("dirs", "dirid") {
|
}
|
||||||
val dir = text("dir")
|
class FileTree {
|
||||||
val parentdirid = integer("parentdirid").references(DirsTable.id)
|
var name = ""
|
||||||
val projectid = integer("projectid").references(ProjectTable.id)
|
var stats = Statistics()
|
||||||
val dirsproj_idx = uniqueIndex("dirsproj_idx", dir, parentdirid, projectid)
|
var authorRisks = mutableMapOf<String, Statistics>()
|
||||||
}
|
var lines = mutableListOf<LineDict>()
|
||||||
object FilesTable : IntIdTable("files", "fileid") {
|
}
|
||||||
val fname = text("fname")
|
class FileEntry(var name : String = "") {
|
||||||
val dirid = integer("dirid").index("filesdir_idx").references(DirsTable.id)
|
var stats = Statistics()
|
||||||
}
|
var authorRisks = mutableMapOf<String, Statistics>()
|
||||||
object LinesTable : IntIdTable("lines", "lineid") {
|
}
|
||||||
val line = text("line")
|
class ProjectTree {
|
||||||
val fileid = integer("fileid").index("linesfile_idx").references(FilesTable.id)
|
var name = "root"
|
||||||
val linenum = integer("linenum")
|
var files = mutableMapOf<Int, FileEntry>()
|
||||||
val linesnumfile_idx = uniqueIndex("linesnumfile_idx", fileid, linenum)
|
var dirs = mutableListOf<Int>()
|
||||||
}
|
}
|
||||||
object AuthorsTable : IntIdTable("authors", "authorid") {
|
class ProjectFilesResult(var fileId : Int, var fname : Path)
|
||||||
val author = text("author").uniqueIndex("authorstrs_idx")
|
|
||||||
}
|
data class Statistics(
|
||||||
object AuthorsGroupsTable : IntIdTable("authorgroups", "authorgroupid") {
|
var totKnowledge : Double = 0.0,
|
||||||
val authors = text("authorsstr").uniqueIndex("authorgroupsstrs_idx")
|
var totRisk : Double = 0.0,
|
||||||
}
|
var totOrphaned : Double = 0.0
|
||||||
object AuthorsAuthorGroupsTable : Table("authors_authorgroups") {
|
) {
|
||||||
val authorid = integer("authorid").references(AuthorsTable.id)
|
constructor(row : ResultRow) :
|
||||||
val groupid = integer("authorgroupid").references(AuthorsGroupsTable.id)
|
this(row[AllocationsTable.knowledge.sum()] ?: 0.0,
|
||||||
override val primaryKey = PrimaryKey(authorid, groupid)
|
row[AllocationsTable.risk.sum()] ?: 0.0,
|
||||||
}
|
row[AllocationsTable.orphaned.sum()] ?: 0.0) {}
|
||||||
object AllocationsTable : IntIdTable("allocations", "allocationid") {
|
}
|
||||||
val knowledge = double("knowledge")
|
class ProjectTreeNode {
|
||||||
val risk = double("risk")
|
var name = "root"
|
||||||
val orphaned = double("orphaned")
|
var files = mutableListOf<FileEntry>()
|
||||||
val lineid = integer("lineid").index("linealloc_idx").references(LinesTable.id)
|
var dirs = mutableListOf<ProjectTreeNode>()
|
||||||
val authorgroupid = integer("authorgroupid").references(AuthorsGroupsTable.id)
|
}
|
||||||
}
|
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"
|
val GIT_BY_A_BUS_BELOW_THRESHOLD = "Git by a Bus Safe Author"
|
||||||
|
|
||||||
init {
|
init {
|
||||||
createTables()
|
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 lineAllocations = (LinesTable leftJoin AllocationsTable)
|
||||||
private val lineAllocationGroups = (lineAllocations leftJoin AuthorsGroupsTable)
|
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[row[FilesTable.id].value] = FileEntry(row[FilesTable.fname])
|
||||||
}
|
}
|
||||||
entry.value.files.entries.forEach { (fileId, fileEntry) ->
|
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)
|
.groupBy(LinesTable.fileid)
|
||||||
.forEach { row ->
|
.forEach { row ->
|
||||||
fileEntry.stats.totKnowledge = row[AllocationsTable.knowledge.sum()] ?: 0.0
|
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) ->
|
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)
|
.groupBy(AllocationsTable.authorgroupid)
|
||||||
.orderBy(AuthorsGroupsTable.authors)
|
.orderBy(AuthorsGroupsTable.authors)
|
||||||
.forEach { row ->
|
.forEach { row ->
|
||||||
@ -227,13 +238,25 @@ class SummaryModel(val db : Database) {
|
|||||||
val root = transformedRoot.dirs.first()
|
val root = transformedRoot.dirs.first()
|
||||||
val projectTree = ProjectTreeResult(project, root)
|
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)
|
.groupBy(AuthorsGroupsTable.id)
|
||||||
.forEach { row ->
|
.forEach { row ->
|
||||||
projectTree.authorRisks[row[AuthorsGroupsTable.authors]] = Statistics(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
|
DirsTable.projectid eq projectId
|
||||||
}.first().let { row ->
|
}.first().let { row ->
|
||||||
projectTree.stats = Statistics(row)
|
projectTree.stats = Statistics(row)
|
||||||
|
Loading…
Reference in New Issue
Block a user