Skip to content

Commit

Permalink
feat(colleagues) - send colleagues info to server (APP-174) (sourcere…
Browse files Browse the repository at this point in the history
  • Loading branch information
asurkov authored Jan 16, 2018
1 parent c1b6105 commit 99c4dc1
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 71 deletions.
2 changes: 2 additions & 0 deletions src/main/kotlin/app/FactCodes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ object FactCodes {
val INDENTATION = 14
val INDENTATION_TABS = 0
val INDENTATION_SPACES = 1

val COLLEAGUES = 15
}
49 changes: 34 additions & 15 deletions src/main/kotlin/app/hashers/CodeLongevity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class CodeLine(val repo: Repository,
/**
* Detects colleagues and their 'work vicinity' from commits.
*/
class Colleagues {
class Colleagues(private val serverRepo: Repo) {
// A map of <colleague_email1, colleague_email2> pairs to pairs of
// <month, time>, which indicates to a minimum time in ms between all line
// changes for these two colleagues in a given month (yyyy-mm).
Expand All @@ -145,9 +145,7 @@ class Colleagues {
if (editorEmail == null || authorEmail == editorEmail) {
return
}
val emails =
if (editorEmail < authorEmail) Pair(editorEmail, authorEmail)
else Pair(authorEmail, editorEmail)
val emails = Pair(authorEmail, editorEmail)

val dates = map.getOrPut(emails, { hashMapOf() })
val month = SimpleDateFormat("yyyy-MM").format(line.editDate)
Expand All @@ -159,15 +157,36 @@ class Colleagues {
}
}

fun updateStats() {
// TODO(alex): report the stats to the server
if (Logger.isDebug) {
map.forEach( { (email1, email2), dates ->
Logger.debug { "<$email1> <$email2>" }
dates.forEach { month, vicinity ->
Logger.debug { " $month: $vicinity ms" }
}
} )
fun calculateAndSendFacts(api: Api) {
// Expose colleagues iff colleague1 edited colleague2 code and
// colleague2 edited colleauge1 code.
val auxHash = hashSetOf<Pair<String, String>>()
for ((pair, dates) in map) {
val email1 = pair.first;
val email2 = pair.second;
if (auxHash.contains(Pair(email2, email1))) {
continue;
}

val min1 = dates.minBy { (_, vicinity) -> vicinity }!!
val dates2 = map.get(Pair(email2, email1));
if (dates2 != null) {
auxHash.add(Pair(email1, email2))

val min2 = dates2.minBy { (_, vicinity) -> vicinity }!!
val min: Long =
if (min1.value < min2.value) { min1.value }
else { min2.value }

val stats = mutableListOf<Fact>()
stats.add(Fact(serverRepo,
FactCodes.COLLEAGUES,
value = email1,
value2 = email2,
value3 = min.toString()))

api.postFacts(stats).onErrorThrow()
}
}
}

Expand Down Expand Up @@ -243,7 +262,7 @@ class CodeLongevity(
catch(e: Exception) { throw Exception("No branch") }

val dataPath = FileHelper.getPath(serverRepo.rehash, "longevity")
val colleagues = Colleagues()
val colleagues = Colleagues(serverRepo)

/**
* Updates code line age statistics on the server.
Expand Down Expand Up @@ -296,7 +315,7 @@ class CodeLongevity(
Logger.info { "Sent ${stats.size} facts to server" }
}

colleagues.updateStats()
colleagues.calculateAndSendFacts(api)
}

/**
Expand Down
6 changes: 5 additions & 1 deletion src/main/kotlin/app/model/Fact.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ data class Fact(
var code: Int = 0,
var key: Int = 0,
var value: String = "",
var author: Author = Author()
var author: Author = Author(),
var value2: String = "",
var value3: String = ""
) {
@Throws(InvalidParameterException::class)
constructor(proto: Protos.Fact) : this() {
Expand All @@ -38,6 +40,8 @@ data class Fact(
.setCode(code)
.setKey(key)
.setValue1(value)
.setValue2(value2)
.setValue3(value3)
.build()
}

Expand Down
55 changes: 0 additions & 55 deletions src/test/kotlin/test/tests/hashers/CodeLongevityTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -555,59 +555,4 @@ class CodeLongevityTest : Spek({
testRepo.destroy()
}
}

given("'colleagues #1'") {
val testRepoPath = "../CodeLongevity_colleagues1"
val testRepo = TestRepo(testRepoPath)
val testRehash = "rehash_colleagues1"
val fileName = "test1.txt"
val author1 = Author(testRepo.userName, testRepo.userEmail)
val author2 = Author("Vasya Pupkin", "[email protected]")
val emails = hashSetOf(author1.email, author2.email)

val serverRepo = Repo(rehash = testRehash)
val mockApi = MockApi(mockRepo = serverRepo)

testRepo.createFile(fileName, listOf("line1", "line2"))
testRepo.commit(message = "initial commit",
author = author1,
date = Calendar.Builder().setTimeOfDay(0, 0, 0)
.build().time)

testRepo.deleteLines(fileName, 1, 1)
testRepo.commit(message = "delete line",
author = author1,
date = Calendar.Builder().setTimeOfDay(0, 1, 0)
.build().time)

testRepo.deleteLines(fileName, 0, 0)
testRepo.commit(message = "delete line #2",
author = author2,
date = Calendar.Builder().setTimeOfDay(0, 1, 0)
.build().time)

val cl = CodeLongevity(serverRepo, emails, testRepo.git)
cl.updateFromObservable(onError = { _ -> fail("exception") },
api = mockApi)

it("'t1'") {
val triple1 = cl.colleagues.get(author1.email)[0]
assertEquals(triple1.first, author2.email,
"Wrong colleague email #1")
assertEquals(triple1.second, "1970-01", "Wrong colleague month #1")
assertEquals(triple1.third, 60, "Wrong colleague vicinity #1")

val triple2 = cl.colleagues.get(author2.email)[0]
assertEquals(triple2.first, author1.email,
"Wrong colleague email #1")
assertEquals(triple2.second, "1970-01", "Wrong colleague month #1")
assertEquals(triple2.third, 60, "Wrong colleague vicinity #1")
}

afterGroup {
CodeLongevity(Repo(rehash = testRehash), emails, testRepo.git)
.dropSavedData()
testRepo.destroy()
}
}
})
147 changes: 147 additions & 0 deletions src/test/kotlin/test/tests/hashers/ColleaguesTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// Copyright 2017 Sourcerer Inc. All Rights Reserved.
// Author: Alexander Surkov ([email protected])

package test.tests.hashers

import app.api.MockApi
import app.FactCodes
import app.hashers.CodeLine
import app.hashers.CodeLineAges
import app.hashers.CodeLongevity
import app.hashers.RevCommitLine
import app.model.*

import test.utils.TestRepo

import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail

import org.eclipse.jgit.revwalk.RevCommit

import org.jetbrains.spek.api.Spek
import org.jetbrains.spek.api.dsl.given
import org.jetbrains.spek.api.dsl.it

import java.util.Calendar
import kotlin.test.assertNotNull

/**
* Testing class.
*/
class ColleaguesTest : Spek({
given("'colleagues #1'") {
val testRepoPath = "../CodeLongevity_colleagues1"
val testRepo = TestRepo(testRepoPath)
val testRehash = "rehash_colleagues1"
val fileName = "test1.txt"
val author1 = Author(testRepo.userName, testRepo.userEmail)
val author2 = Author("Vasya Pupkin", "[email protected]")
val emails = hashSetOf(author1.email, author2.email)

val serverRepo = Repo(rehash = testRehash)
val mockApi = MockApi(mockRepo = serverRepo)

testRepo.createFile(fileName, listOf("line1", "line2"))
testRepo.commit(message = "initial commit",
author = author1,
date = Calendar.Builder().setTimeOfDay(0, 0, 0)
.build().time)

testRepo.deleteLines(fileName, 1, 1)
testRepo.commit(message = "delete line",
author = author1,
date = Calendar.Builder().setTimeOfDay(0, 1, 0)
.build().time)

testRepo.deleteLines(fileName, 0, 0)
testRepo.commit(message = "delete line #2",
author = author2,
date = Calendar.Builder().setTimeOfDay(0, 1, 0)
.build().time)

val cl = CodeLongevity(serverRepo, emails, testRepo.git)
cl.updateFromObservable(onError = { _ -> fail("exception") },
api = mockApi)

it("'t1'") {
val triple1 = cl.colleagues.get(author1.email)[0]
assertEquals(triple1.first, author2.email,
"Wrong colleague email #1")
assertEquals(triple1.second, "1970-01", "Wrong colleague month #1")
assertEquals(triple1.third, 60, "Wrong colleague vicinity #1")

val triple2 = cl.colleagues.get(author2.email)[0]
assertEquals(triple2.first, author1.email,
"Wrong colleague email #1")
assertEquals(triple2.second, "1970-01", "Wrong colleague month #1")
assertEquals(triple2.third, 60, "Wrong colleague vicinity #1")
}

afterGroup {
CodeLongevity(Repo(rehash = testRehash), emails, testRepo.git)
.dropSavedData()
testRepo.destroy()
}
}

given("'colleagues stats'") {
val testRepoPath = "../CodeLongevity_colleagues_stats"
val testRepo = TestRepo(testRepoPath)
val testRehash = "rehash_lngstats2"
val fileName = "test1.txt"
val author1 = Author(testRepo.userName, testRepo.userEmail)
val author2 = Author("Vasya Pupkin", "[email protected]")
val emails = hashSetOf(author1.email, author2.email)

val serverRepo = Repo(rehash = testRehash)
val mockApi = MockApi(mockRepo = serverRepo)

testRepo.createFile(fileName, listOf("line1", "line2"))
testRepo.commit(message = "initial commit",
author = author1,
date = Calendar.Builder().setTimeOfDay(0, 0, 0)
.build().time)

testRepo.deleteLines(fileName, 1, 1)
testRepo.commit(message = "delete line",
author = author2,
date = Calendar.Builder().setTimeOfDay(0, 1, 0)
.build().time)

testRepo.insertLines(fileName, 1, listOf("line in the end"))
testRepo.commit(message = "insert line",
author = author2,
date = Calendar.Builder().setTimeOfDay(0, 10, 0)
.build().time)

testRepo.deleteLines(fileName, 1, 1)
testRepo.commit(message = "delete line #2",
author = author1,
date = Calendar.Builder().setTimeOfDay(0, 20, 0)
.build().time)

CodeLongevity(serverRepo, emails, testRepo.git)
.updateFromObservable(onError = { _ -> fail("exception") },
api = mockApi)

it("'t1'") {
for (f in mockApi.receivedFacts) {
println(f)
}
assertTrue(mockApi.receivedFacts.contains(
Fact(repo = serverRepo,
code = FactCodes.COLLEAGUES,
value = author2.email,
value2 = author1.email,
value3 = (60).toString())
))
}

afterGroup {
CodeLongevity(Repo(rehash = testRehash), emails, testRepo.git)
.dropSavedData()
testRepo.destroy()
}
}
})

0 comments on commit 99c4dc1

Please sign in to comment.