Finish summary model

This commit is contained in:
Matt Soucy 2020-06-27 18:22:13 -04:00
parent da895cbc91
commit f754b90353
5 changed files with 424 additions and 336 deletions

View File

@ -0,0 +1,254 @@
package me.msoucy.gbat.models
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
import me.msoucy.gbat.copyOf
import me.msoucy.gbat.mutableCopyOf
class KnowledgeModel(val db : Database, val constant : Double, val riskModel : RiskModel) {
class KnowledgeAcct(var knowledgeAcctId : Int,
var authors : List<String>,
var authorsStr : String)
object AuthorsTable : Table("authors") {
val id = integer("authorid")
val author = text("author").uniqueIndex("authors_idx")
override val primaryKey = PrimaryKey(id)
}
object KnowledgeAcctsTable : Table("knowledgeaccts") {
val id = integer("knowledgeacctid")
val authors = text("authors").uniqueIndex("knowledgeacctsauthors_idx")
override val primaryKey = PrimaryKey(id)
}
object KnowledgeAuthorsTable : Table("knowedgeaccts_authors") {
val knowledgeacctid = integer("knowledgeacctid")
val authorid = integer("authorid")
override val primaryKey = PrimaryKey(knowledgeacctid, authorid)
}
object LineKnowledge : Table("lineknowledge") {
val linenum = integer("linenum")
val knowledgeacctid = integer("knowledgeacctid")
val knowledge = double("knowledge")
}
init {
createTables()
}
val SAFE_AUTHOR_ID = 1
val SAFE_KNOWLEDGE_ACCT_ID = 1
val KNOWLEDGE_PER_LINE_ADDED = 1000.0
fun applyChange(changeType : ChangeType, author : String, lineNum : Int) = when(changeType) {
ChangeType.Add -> lineAdded(author, lineNum)
ChangeType.Change -> lineChanged(author, lineNum)
ChangeType.Remove -> lineRemoved(lineNum)
}
fun lineChanged(author : String, lineNum : Int) {
val kCreated = constant * KNOWLEDGE_PER_LINE_ADDED
val kAcquired = (1 - constant) * KNOWLEDGE_PER_LINE_ADDED
val totLineK = totalLineKnowledge(lineNum)
val acquiredPct = if (totLineK != 0.0) {
kAcquired / totLineK
} else 0.0
redistributeKnowledge(author, lineNum, acquiredPct)
val knowledgeAcctId = lookupOrCreateKnowledgeAcct(listOf(author))
adjustKnowledge(knowledgeAcctId, lineNum, kCreated)
}
fun lineRemoved(lineNum : Int) {
allAcctsWithKnowledgeOf(lineNum).forEach {
destroyLineKnowledge(it, lineNum)
}
bumpAllLinesFrom(lineNum, -1)
}
fun lineAdded(author : String, lineNum : Int) {
val knowledgeAcctId = lookupOrCreateKnowledgeAcct(listOf(author))
bumpAllLinesFrom(lineNum-1, 1)
adjustKnowledge(knowledgeAcctId, lineNum, KNOWLEDGE_PER_LINE_ADDED)
}
fun knowledgeSummary(lineNum : Int) = transaction(db) {
LineKnowledge.select {
LineKnowledge.linenum eq lineNum
}.map {
Pair(getKnowledgeAcct(it[LineKnowledge.knowledgeacctid]).authors,
it[LineKnowledge.knowledge])
}.sortedBy {
it.first.joinToString("\n")
}.copyOf()
}
private fun bumpAllLinesFrom(lineNum : Int, adjustment : Int) = transaction(db) {
LineKnowledge.update({LineKnowledge.linenum greater lineNum}) {
with(SqlExpressionBuilder) {
it[LineKnowledge.linenum] = LineKnowledge.linenum + adjustment
}
}
}
private fun getKnowledgeAcct(knowledgeAcctId : Int) = transaction(db) {
KnowledgeAcctsTable.select {
KnowledgeAcctsTable.id eq knowledgeAcctId
}.map {
KnowledgeAcct(
it[KnowledgeAcctsTable.id],
it[KnowledgeAcctsTable.authors].split("\n"),
it[KnowledgeAcctsTable.authors]
)
}.first()
}
private fun destroyLineKnowledge(knowledgeId : Int, lineNum : Int) = transaction(db) {
LineKnowledge.deleteWhere {
(LineKnowledge.knowledgeacctid eq knowledgeId) and
(LineKnowledge.linenum eq lineNum)
}
}
private fun redistributeKnowledge(author : String, lineNum : Int, redistPct : Double) {
if(riskModel.isDeparted(author)) {
return
}
val knowledgeIds = nonSafeAcctsWithKnowledgeOf(lineNum)
for (knowledgeId in knowledgeIds) {
val knowledgeAcct = getKnowledgeAcct(knowledgeId)
if (author !in knowledgeAcct.authors) {
val oldKnowledge = knowledgeInAcct(knowledgeAcct.knowledgeAcctId, lineNum)
var newAuthors = knowledgeAcct.authors.mutableCopyOf()
if(newAuthors.all(riskModel::isDeparted)) {
newAuthors = mutableListOf(author)
} else {
newAuthors.add(author)
}
newAuthors = newAuthors.sorted().mutableCopyOf()
val newKnowledgeId = if(riskModel.jointBusProbBelowThreshold(*newAuthors.toTypedArray())) {
SAFE_KNOWLEDGE_ACCT_ID
} else {
lookupOrCreateKnowledgeAcct(newAuthors)
}
val knowledgeToDist = oldKnowledge * redistPct
adjustKnowledge(knowledgeId, lineNum, -knowledgeToDist)
adjustKnowledge(newKnowledgeId, lineNum, knowledgeToDist)
}
}
}
private fun knowledgeInAcct(knowledgeAcctId : Int, lineNum : Int) = transaction(db) {
LineKnowledge.select {
(LineKnowledge.knowledgeacctid eq knowledgeAcctId) and
(LineKnowledge.linenum eq lineNum)
}.map {
it[LineKnowledge.knowledge]
}.first()
}
private fun nonSafeAcctsWithKnowledgeOf(lineNum : Int) = transaction(db) {
LineKnowledge.select {
(LineKnowledge.linenum eq lineNum) and
(LineKnowledge.knowledgeacctid neq SAFE_KNOWLEDGE_ACCT_ID)
}.map {
it[LineKnowledge.knowledgeacctid]
}
}
private fun allAcctsWithKnowledgeOf(lineNum : Int) = transaction(db) {
LineKnowledge.select {
LineKnowledge.linenum eq lineNum
}.map {
it[LineKnowledge.knowledgeacctid]
}
}
private fun adjustKnowledge(knowledgeAcctId : Int, lineNum : Int, adjustment : Double) = transaction(db) {
val lineExists = LineKnowledge.select {
(LineKnowledge.knowledgeacctid eq knowledgeAcctId) and
(LineKnowledge.linenum eq lineNum)
}.count() > 0
if(!lineExists) {
LineKnowledge.insert {
it[LineKnowledge.knowledgeacctid] = knowledgeAcctId
it[LineKnowledge.linenum] = lineNum
it[LineKnowledge.knowledge] = 0.0
}
}
LineKnowledge.update({
(LineKnowledge.knowledgeacctid eq knowledgeAcctId) and
(LineKnowledge.linenum eq lineNum)
}) {
with(SqlExpressionBuilder) {
it[LineKnowledge.knowledge] = LineKnowledge.knowledge + adjustment
}
}
}
private fun lookupOrCreateKnowledgeAcct(authors : List<String>) = transaction(db) {
val authorStr = authors.sorted().joinToString("\n")
var newId = KnowledgeAcctsTable.select {
KnowledgeAcctsTable.authors eq authorStr
}.first().let {
it[KnowledgeAcctsTable.id]
}
if (newId != -1) {
KnowledgeAcctsTable.insert {
it[KnowledgeAcctsTable.authors] = authorStr
}
newId = KnowledgeAcctsTable.select {
KnowledgeAcctsTable.authors eq authorStr
}.map {
it[KnowledgeAcctsTable.id]
}.first()
authors.map(::lookupOrCreateAuthor).forEach { authorId ->
KnowledgeAuthorsTable.insert {
it[KnowledgeAuthorsTable.knowledgeacctid] = newId
it[KnowledgeAuthorsTable.authorid] = authorId
}
}
}
newId
}
private fun lookupOrCreateAuthor(authorName : String) = transaction(db) {
AuthorsTable.insertIgnore {
it[author] = authorName
}
AuthorsTable.select {
AuthorsTable.author eq authorName
}.first().let {
it[AuthorsTable.id]
}
}
private fun totalLineKnowledge(linenum : Int) = transaction(db) {
LineKnowledge.select {
LineKnowledge.linenum eq linenum
}.first().let {
it[LineKnowledge.knowledge]
}
}
private fun createTables() = transaction(db) {
SchemaUtils.createMissingTablesAndColumns(AuthorsTable, KnowledgeAcctsTable, KnowledgeAuthorsTable, LineKnowledge)
AuthorsTable.insertIgnore {
it[id] = 1
it[author] = ""
}
KnowledgeAcctsTable.insertIgnore {
it[id] = 1
it[authors] = ""
}
KnowledgeAuthorsTable.insertIgnore {
it[knowledgeacctid] = SAFE_KNOWLEDGE_ACCT_ID
it[authorid] = SAFE_AUTHOR_ID
}
}
}

View File

@ -0,0 +1,45 @@
package me.msoucy.gbat.models
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.io.forEachLine
import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
class LineModel() {
inner class Line(var num : Int, var text : String)
val model = mutableSetOf<Line>()
fun applyChange(changeType : ChangeType, lineNum : Int, lineText : String) = when(changeType) {
ChangeType.Add -> add(Line(lineNum, lineText))
ChangeType.Change -> change(Line(lineNum, lineText))
ChangeType.Remove -> del(Line(lineNum, lineText))
}
fun add(line : Line) {
model.onEach { entry ->
if(entry.num >= line.num) {
entry.num++
}
}
model.add(line)
}
fun del(line : Line) {
model.removeIf { it.num == line.num }
model.onEach { entry ->
if(entry.num > line.num) {
entry.num--
}
}
}
fun change(line : Line) {
model.removeIf { it.num == line.num }
model.add(line)
}
fun get() = model.sortedBy { it.num }.map { it.text }
}

View File

@ -0,0 +1,5 @@
package me.msoucy.gbat.models
enum class ChangeType {
Add, Change, Remove
}

View File

@ -0,0 +1,55 @@
package me.msoucy.gbat.models
import java.io.File
import kotlin.io.forEachLine
class RiskModel(val threshold : Double,
val default : Double,
val busRiskFile : File?,
val departedFile : File?) {
val departed = mutableSetOf<String>()
val risks = mutableMapOf<String, Double>().withDefault {default}
init {
parseBusRisks()
parseDeparted()
}
operator fun get(author : String) : Double {
val name = author.trim()
if(name.isEmpty()) {
return threshold
}
return risks.getOrPut(name) { default }
}
fun isDeparted(author : String) = author.trim() in departed
fun jointBusProb(vararg authors : String) =
authors.map { this[it] }.reduce { a, b -> a * b }
fun jointBusProbBelowThreshold(vararg authors : String) =
jointBusProb(*authors) <= threshold
private fun parseBusRisks() {
busRiskFile?.forEachLine { line ->
val sline = line.trim()
if(sline.isNotEmpty()) {
val segments = sline.split("=")
val risk = segments.last()
val author = segments.dropLast(1).joinToString(separator="=")
risks[author] = risk.toDouble()
}
}
}
private fun parseDeparted() {
departedFile?.forEachLine { line ->
val author = line.trim()
if(author.isNotEmpty()) {
risks[author] = 1.0
departed.add(author)
}
}
}
}

View File

@ -1,346 +1,24 @@
package me.msoucy.gbat package me.msoucy.gbat.models
import java.io.File import java.io.File
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
import kotlin.io.forEachLine
import org.jetbrains.exposed.dao.id.IntIdTable 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
enum class ChangeType { class CondensedAnalysis {
Add, Change, Remove class LineSummary {
} var authors = listOf<String>()
var knowledge = 0.0
class RiskModel(val threshold : Double, var risk = 0.0
val default : Double, var orphaned = 0.0
val busRiskFile : File?, }
val departedFile : File?) { var repoRoot = ""
val departed = mutableSetOf<String>() var project = ""
val risks = mutableMapOf<String, Double>().withDefault {default} var projectRoot = ""
var fileName = ""
init { var lineSummaries = mutableListOf<Pair<String, List<LineSummary>>>()
parseBusRisks()
parseDeparted()
}
operator fun get(author : String) : Double {
val name = author.trim()
if(name.isEmpty()) {
return threshold
}
return risks.getOrPut(name) { default }
}
fun isDeparted(author : String) = author.trim() in departed
fun jointBusProb(vararg authors : String) =
authors.map { this[it] }.reduce { a, b -> a * b }
fun jointBusProbBelowThreshold(vararg authors : String) =
jointBusProb(*authors) <= threshold
private fun parseBusRisks() {
busRiskFile?.forEachLine { line ->
val sline = line.trim()
if(sline.isNotEmpty()) {
val segments = sline.split("=")
val risk = segments.last()
val author = segments.dropLast(1).joinToString(separator="=")
risks[author] = risk.toDouble()
}
}
}
private fun parseDeparted() {
departedFile?.forEachLine { line ->
val author = line.trim()
if(author.isNotEmpty()) {
risks[author] = 1.0
departed.add(author)
}
}
}
}
class LineModel() {
inner class Line(var num : Int, var text : String)
val model = mutableSetOf<Line>()
fun applyChange(changeType : ChangeType, lineNum : Int, lineText : String) = when(changeType) {
ChangeType.Add -> add(Line(lineNum, lineText))
ChangeType.Change -> change(Line(lineNum, lineText))
ChangeType.Remove -> del(Line(lineNum, lineText))
}
fun add(line : Line) {
model.onEach { entry ->
if(entry.num >= line.num) {
entry.num++
}
}
model.add(line)
}
fun del(line : Line) {
model.removeIf { it.num == line.num }
model.onEach { entry ->
if(entry.num > line.num) {
entry.num--
}
}
}
fun change(line : Line) {
model.removeIf { it.num == line.num }
model.add(line)
}
fun get() = model.sortedBy { it.num }.map { it.text }
}
class KnowledgeModel(val db : Database, val constant : Double, val riskModel : RiskModel) {
class KnowledgeAcct(var knowledgeAcctId : Int,
var authors : List<String>,
var authorsStr : String)
object AuthorsTable : Table("authors") {
val id = integer("authorid")
val author = text("author").uniqueIndex("authors_idx")
override val primaryKey = PrimaryKey(id)
}
object KnowledgeAcctsTable : Table("knowledgeaccts") {
val id = integer("knowledgeacctid")
val authors = text("authors").uniqueIndex("knowledgeacctsauthors_idx")
override val primaryKey = PrimaryKey(id)
}
object KnowledgeAuthorsTable : Table("knowedgeaccts_authors") {
val knowledgeacctid = integer("knowledgeacctid")
val authorid = integer("authorid")
override val primaryKey = PrimaryKey(knowledgeacctid, authorid)
}
object LineKnowledge : Table("lineknowledge") {
val linenum = integer("linenum")
val knowledgeacctid = integer("knowledgeacctid")
val knowledge = double("knowledge")
}
init {
createTables()
}
val SAFE_AUTHOR_ID = 1
val SAFE_KNOWLEDGE_ACCT_ID = 1
val KNOWLEDGE_PER_LINE_ADDED = 1000.0
fun applyChange(changeType : ChangeType, author : String, lineNum : Int) = when(changeType) {
ChangeType.Add -> lineAdded(author, lineNum)
ChangeType.Change -> lineChanged(author, lineNum)
ChangeType.Remove -> lineRemoved(lineNum)
}
fun lineChanged(author : String, lineNum : Int) {
val kCreated = constant * KNOWLEDGE_PER_LINE_ADDED
val kAcquired = (1 - constant) * KNOWLEDGE_PER_LINE_ADDED
val totLineK = totalLineKnowledge(lineNum)
val acquiredPct = if (totLineK != 0.0) {
kAcquired / totLineK
} else 0.0
redistributeKnowledge(author, lineNum, acquiredPct)
val knowledgeAcctId = lookupOrCreateKnowledgeAcct(listOf(author))
adjustKnowledge(knowledgeAcctId, lineNum, kCreated)
}
fun lineRemoved(lineNum : Int) {
allAcctsWithKnowledgeOf(lineNum).forEach {
destroyLineKnowledge(it, lineNum)
}
bumpAllLinesFrom(lineNum, -1)
}
fun lineAdded(author : String, lineNum : Int) {
val knowledgeAcctId = lookupOrCreateKnowledgeAcct(listOf(author))
bumpAllLinesFrom(lineNum-1, 1)
adjustKnowledge(knowledgeAcctId, lineNum, KNOWLEDGE_PER_LINE_ADDED)
}
fun knowledgeSummary(lineNum : Int) = transaction(db) {
LineKnowledge.select {
LineKnowledge.linenum eq lineNum
}.map {
Pair(getKnowledgeAcct(it[LineKnowledge.knowledgeacctid]).authors,
it[LineKnowledge.knowledge])
}.sortedBy {
it.first.joinToString("\n")
}.copyOf()
}
private fun bumpAllLinesFrom(lineNum : Int, adjustment : Int) = transaction(db) {
LineKnowledge.update({LineKnowledge.linenum greater lineNum}) {
with(SqlExpressionBuilder) {
it[LineKnowledge.linenum] = LineKnowledge.linenum + adjustment
}
}
}
private fun getKnowledgeAcct(knowledgeAcctId : Int) = transaction(db) {
KnowledgeAcctsTable.select {
KnowledgeAcctsTable.id eq knowledgeAcctId
}.map {
KnowledgeAcct(
it[KnowledgeAcctsTable.id],
it[KnowledgeAcctsTable.authors].split("\n"),
it[KnowledgeAcctsTable.authors]
)
}.first()
}
private fun destroyLineKnowledge(knowledgeId : Int, lineNum : Int) = transaction(db) {
LineKnowledge.deleteWhere {
(LineKnowledge.knowledgeacctid eq knowledgeId) and
(LineKnowledge.linenum eq lineNum)
}
}
private fun redistributeKnowledge(author : String, lineNum : Int, redistPct : Double) {
if(riskModel.isDeparted(author)) {
return
}
val knowledgeIds = nonSafeAcctsWithKnowledgeOf(lineNum)
for (knowledgeId in knowledgeIds) {
val knowledgeAcct = getKnowledgeAcct(knowledgeId)
if (author !in knowledgeAcct.authors) {
val oldKnowledge = knowledgeInAcct(knowledgeAcct.knowledgeAcctId, lineNum)
var newAuthors = knowledgeAcct.authors.mutableCopyOf()
if(newAuthors.all(riskModel::isDeparted)) {
newAuthors = mutableListOf(author)
} else {
newAuthors.add(author)
}
newAuthors = newAuthors.sorted().mutableCopyOf()
val newKnowledgeId = if(riskModel.jointBusProbBelowThreshold(*newAuthors.toTypedArray())) {
SAFE_KNOWLEDGE_ACCT_ID
} else {
lookupOrCreateKnowledgeAcct(newAuthors)
}
val knowledgeToDist = oldKnowledge * redistPct
adjustKnowledge(knowledgeId, lineNum, -knowledgeToDist)
adjustKnowledge(newKnowledgeId, lineNum, knowledgeToDist)
}
}
}
private fun knowledgeInAcct(knowledgeAcctId : Int, lineNum : Int) = transaction(db) {
LineKnowledge.select {
(LineKnowledge.knowledgeacctid eq knowledgeAcctId) and
(LineKnowledge.linenum eq lineNum)
}.map {
it[LineKnowledge.knowledge]
}.first()
}
private fun nonSafeAcctsWithKnowledgeOf(lineNum : Int) = transaction(db) {
LineKnowledge.select {
(LineKnowledge.linenum eq lineNum) and
(LineKnowledge.knowledgeacctid neq SAFE_KNOWLEDGE_ACCT_ID)
}.map {
it[LineKnowledge.knowledgeacctid]
}
}
private fun allAcctsWithKnowledgeOf(lineNum : Int) = transaction(db) {
LineKnowledge.select {
LineKnowledge.linenum eq lineNum
}.map {
it[LineKnowledge.knowledgeacctid]
}
}
private fun adjustKnowledge(knowledgeAcctId : Int, lineNum : Int, adjustment : Double) = transaction(db) {
val lineExists = LineKnowledge.select {
(LineKnowledge.knowledgeacctid eq knowledgeAcctId) and
(LineKnowledge.linenum eq lineNum)
}.count() > 0
if(!lineExists) {
LineKnowledge.insert {
it[LineKnowledge.knowledgeacctid] = knowledgeAcctId
it[LineKnowledge.linenum] = lineNum
it[LineKnowledge.knowledge] = 0.0
}
}
LineKnowledge.update({
(LineKnowledge.knowledgeacctid eq knowledgeAcctId) and
(LineKnowledge.linenum eq lineNum)
}) {
with(SqlExpressionBuilder) {
it[LineKnowledge.knowledge] = LineKnowledge.knowledge + adjustment
}
}
}
private fun lookupOrCreateKnowledgeAcct(authors : List<String>) = transaction(db) {
val authorStr = authors.sorted().joinToString("\n")
var newId = KnowledgeAcctsTable.select {
KnowledgeAcctsTable.authors eq authorStr
}.first().let {
it[KnowledgeAcctsTable.id]
}
if (newId != -1) {
KnowledgeAcctsTable.insert {
it[KnowledgeAcctsTable.authors] = authorStr
}
newId = KnowledgeAcctsTable.select {
KnowledgeAcctsTable.authors eq authorStr
}.map {
it[KnowledgeAcctsTable.id]
}.first()
authors.map(::lookupOrCreateAuthor).forEach { authorId ->
KnowledgeAuthorsTable.insert {
it[KnowledgeAuthorsTable.knowledgeacctid] = newId
it[KnowledgeAuthorsTable.authorid] = authorId
}
}
}
newId
}
private fun lookupOrCreateAuthor(authorName : String) = transaction(db) {
AuthorsTable.insertIgnore {
it[author] = authorName
}
AuthorsTable.select {
AuthorsTable.author eq authorName
}.first().let {
it[AuthorsTable.id]
}
}
private fun totalLineKnowledge(linenum : Int) = transaction(db) {
LineKnowledge.select {
LineKnowledge.linenum eq linenum
}.first().let {
it[LineKnowledge.knowledge]
}
}
private fun createTables() = transaction(db) {
SchemaUtils.createMissingTablesAndColumns(AuthorsTable, KnowledgeAcctsTable, KnowledgeAuthorsTable, LineKnowledge)
AuthorsTable.insertIgnore {
it[id] = 1
it[author] = ""
}
KnowledgeAcctsTable.insertIgnore {
it[id] = 1
it[authors] = ""
}
KnowledgeAuthorsTable.insertIgnore {
it[knowledgeacctid] = SAFE_KNOWLEDGE_ACCT_ID
it[authorid] = SAFE_AUTHOR_ID
}
}
} }
class SummaryModel(val db : Database) { class SummaryModel(val db : Database) {
@ -432,6 +110,57 @@ class SummaryModel(val db : Database) {
private val manyJoined = (lineAllocations leftJoin FilesTable leftJoin DirsTable) private val manyJoined = (lineAllocations leftJoin FilesTable leftJoin DirsTable)
private val allJoined = (manyJoined leftJoin AuthorsGroupsTable) private val allJoined = (manyJoined leftJoin AuthorsGroupsTable)
fun summarize(ca : CondensedAnalysis) {
val fname = adjustFname(File(ca.repoRoot), File(ca.projectRoot), File(ca.fileName))
val projectId = findOrCreateProject(ca.project)
var parentDirId = 0
splitAllDirs(fname.parentFile).forEach {
parentDirId = findOrCreateDir(it.toString(), projectId, parentDirId)
}
val fileId = createFile(fname.name, parentDirId)
ca.lineSummaries.forEachIndexed { index, (line, allocations) ->
val lineNum = index + 1
val lineId = createLine(line, lineNum, fileId)
allocations.forEach { alloc ->
val authors = alloc.authors.map(::safeAuthorName)
val authorGroupId = findOrCreateAuthorGroup(authors)
createAllocation(alloc.knowledge, alloc.risk, alloc.orphaned, authorGroupId, lineId)
}
}
}
fun totalKnowledge() = transaction(db) {
AllocationsTable.selectAll().map { it[AllocationsTable.knowledge] }.sum()
}
fun totalRisk() = transaction(db) {
AllocationsTable.selectAll().map { it[AllocationsTable.risk] }.sum()
}
fun totalOrphaned() = transaction(db) {
AllocationsTable.selectAll().map { it[AllocationsTable.orphaned] }.sum()
}
fun countFiles() = transaction(db) {
FilesTable.selectAll().count()
}
fun authorgroupsWithRisk(top : Int? = null) : List<Pair<String, Double>> = transaction(db) {
var query = (AllocationsTable innerJoin AuthorsGroupsTable)
.selectAll()
.groupBy(AuthorsGroupsTable.authors)
.orderBy(AllocationsTable.risk.sum() to SortOrder.DESC)
if(top != null) {
query = query.limit(top)
}
query.map {
it[AuthorsGroupsTable.authors] to (it[AllocationsTable.risk.sum()] ?: 0.0)
}
}
fun fileidsWithRisk(top : Int? = null) : List<Pair<Int, Double>> = transaction(db) { fun fileidsWithRisk(top : Int? = null) : List<Pair<Int, Double>> = transaction(db) {
var query = (FilesTable leftJoin LinesTable leftJoin AllocationsTable) var query = (FilesTable leftJoin LinesTable leftJoin AllocationsTable)
.selectAll() .selectAll()
@ -456,7 +185,7 @@ class SummaryModel(val db : Database) {
fun projectFiles(project : String) : List<ProjectFilesResult> = transaction(db) { fun projectFiles(project : String) : List<ProjectFilesResult> = transaction(db) {
val projectId = findOrCreateProject(project) val projectId = findOrCreateProject(project)
return (FilesTable innerJoin DirsTable).select { (FilesTable innerJoin DirsTable).select {
(FilesTable.dirid eq DirsTable.id) and (FilesTable.dirid eq DirsTable.id) and
(DirsTable.projectid eq projectId) (DirsTable.projectid eq projectId)
}.map { row -> }.map { row ->
@ -517,7 +246,7 @@ class SummaryModel(val db : Database) {
} }
manyJoined.select { manyJoined.select {
DirsTable.projectid eq DirsTable.projectid eq projectId
}.first().let { row -> }.first().let { row ->
projectTree.stats = Statistics(row) projectTree.stats = Statistics(row)
} }