Add large examples and questions
This commit is contained in:
parent
97bbddbdfc
commit
b0e181aaae
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
|
6
.idea/kotlinc.xml
Normal file
6
.idea/kotlinc.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="KotlinJpsPluginSettings">
|
||||||
|
<option name="version" value="1.9.10" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -1,5 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.9.10"
|
kotlin("jvm") version "1.9.10"
|
||||||
|
kotlin("plugin.serialization") version "1.9.10"
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "center.sciprog"
|
group = "center.sciprog"
|
||||||
@ -11,6 +12,8 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.1")
|
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.1")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
||||||
testImplementation(kotlin("test"))
|
testImplementation(kotlin("test"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
questions.md
Normal file
10
questions.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
* Создание объектов
|
||||||
|
* Стоит ли использовать вторичные конструкторы или лучше фабричные методы в компаньоне
|
||||||
|
* Что лучше - публичный конструктор или приватный с фабричным методом в компаньоне
|
||||||
|
* Проверка параметров в публичном конструкторе или в фабричном методе с передачей в приватный конструктор
|
||||||
|
* init блок или специальный метод init() в классах и object
|
||||||
|
* Enum VS sealed
|
||||||
|
* Когда использовать `T.() -> R`, а когда `(T) -> R`, а если два параметра, то `T.(T2) -> R`, `T2.(T) -> R`, или `(T, T2) -> R`
|
||||||
|
* Обновление кэша
|
||||||
|
* Выбор обработчика по объекту событию/полю объекта
|
||||||
|
* `a.b!! -> a.b ?: error("b should be not a null")`
|
92
src/main/kotlin/WikiGame.kt
Normal file
92
src/main/kotlin/WikiGame.kt
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Смотреть доклад тут: https://jokerconf.com/talks/726fdf3540524be28c8f5901c1800583
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface WikiGame {
|
||||||
|
fun play(startPageTitle: String, endPageTitle: String, maxDepth: Int): List<String?>
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Page(val title: String, val parentPage: Page?) : Comparable<Page> {
|
||||||
|
override fun compareTo(other: Page): Int {
|
||||||
|
return title.compareTo(other.title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface WikiRemoteDataSource {
|
||||||
|
suspend fun getLinksByTitle(title: String): List<String>
|
||||||
|
|
||||||
|
suspend fun getBacklinksByTitle(title: String): List<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
class WikiGameCoroImpl : WikiGame {
|
||||||
|
private val wikiRemoteDataSource: WikiRemoteDataSource = TODO()
|
||||||
|
|
||||||
|
override fun play(startPageTitle: String, endPageTitle: String, maxDepth: Int): List<String> = runBlocking {
|
||||||
|
val visitedPages: MutableMap<String, Boolean> = ConcurrentHashMap()
|
||||||
|
|
||||||
|
val startPage = Page(startPageTitle, null)
|
||||||
|
|
||||||
|
val resultPage = processPage(startPage, endPageTitle, 0, maxDepth, visitedPages)
|
||||||
|
|
||||||
|
val path = mutableListOf<String>()
|
||||||
|
|
||||||
|
var curPg: Page? = resultPage
|
||||||
|
do {
|
||||||
|
path.add(curPg!!.title)
|
||||||
|
curPg = curPg.parentPage
|
||||||
|
} while (curPg != null)
|
||||||
|
|
||||||
|
return@runBlocking path.reversed()
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun processPage(
|
||||||
|
page: Page,
|
||||||
|
endPageTitle: String,
|
||||||
|
curDepth: Int,
|
||||||
|
maxDepth: Int,
|
||||||
|
visitedPages: MutableMap<String, Boolean>,
|
||||||
|
): Page {
|
||||||
|
if (visitedPages.putIfAbsent(page.title, true) != null) {
|
||||||
|
throw RuntimeException("Already visited")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page.title == endPageTitle) {
|
||||||
|
return page
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curDepth == maxDepth) {
|
||||||
|
throw RuntimeException("Depth reached")
|
||||||
|
}
|
||||||
|
|
||||||
|
val links = wikiRemoteDataSource.getLinksByTitle(page.title)
|
||||||
|
|
||||||
|
val pageChannel = Channel<Page>()
|
||||||
|
|
||||||
|
val scope = CoroutineScope(SupervisorJob() + CoroutineExceptionHandler { _, _ -> })
|
||||||
|
links.forEach { link ->
|
||||||
|
scope.launch {
|
||||||
|
val pageResult = processPage(
|
||||||
|
Page(link, page),
|
||||||
|
endPageTitle,
|
||||||
|
curDepth + 1,
|
||||||
|
maxDepth,
|
||||||
|
visitedPages,
|
||||||
|
)
|
||||||
|
|
||||||
|
pageChannel.send(pageResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val resultPage = pageChannel.receive()
|
||||||
|
|
||||||
|
scope.cancel()
|
||||||
|
|
||||||
|
return resultPage
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.jokerconf.kotlin.idiomatik
|
package com.jokerconf.kotlin.idiomatik.conference
|
||||||
|
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlin.time.Duration.Companion.minutes
|
import kotlin.time.Duration.Companion.minutes
|
@ -1,4 +1,4 @@
|
|||||||
package com.jokerconf.kotlin.idiomatik
|
package com.jokerconf.kotlin.idiomatik.conference
|
||||||
|
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
@ -1,4 +1,4 @@
|
|||||||
package com.jokerconf.kotlin.idiomatik
|
package com.jokerconf.kotlin.idiomatik.conference
|
||||||
|
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
@ -1,4 +1,4 @@
|
|||||||
package com.jokerconf.kotlin.idiomatik
|
package com.jokerconf.kotlin.idiomatik.conference
|
||||||
|
|
||||||
class Speaker {
|
class Speaker {
|
||||||
var name: String? = null
|
var name: String? = null
|
53
src/main/kotlin/versionPuller.kt
Normal file
53
src/main/kotlin/versionPuller.kt
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.net.URI
|
||||||
|
|
||||||
|
const val token = "********"
|
||||||
|
const val BASE_API_URL = "http://gitlab.com/api/v4"
|
||||||
|
const val SECURITY_QUERY_PARAM = "private_token=${token}"
|
||||||
|
const val GET_PROJECT_BY_NAME_PATH_TEMPLATE = "$BASE_API_URL/projects?search=%s&$SECURITY_QUERY_PARAM"
|
||||||
|
const val GET_ALL_TAGS_BY_PROJECT_ID_PATH_TEMPLATE = "$BASE_API_URL/projects/%d/repository/tags?$SECURITY_QUERY_PARAM"
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val json = Json { ignoreUnknownKeys = true }
|
||||||
|
listOf(
|
||||||
|
"ProjectA",
|
||||||
|
"ProjectB",
|
||||||
|
"ProjectC",
|
||||||
|
).forEach { projectName ->
|
||||||
|
val projectsJson = httpGet(GET_PROJECT_BY_NAME_PATH_TEMPLATE.format(projectName))
|
||||||
|
val projects = json.decodeFromString<List<Project>>(projectsJson)
|
||||||
|
|
||||||
|
projects
|
||||||
|
.filter { it.name == projectName }
|
||||||
|
.forEach {
|
||||||
|
val tagsJson = httpGet(GET_ALL_TAGS_BY_PROJECT_ID_PATH_TEMPLATE.format(it.id))
|
||||||
|
val tags = json.decodeFromString<List<Tag>>(tagsJson)
|
||||||
|
val lastTag = tags.map(Tag::name).maxWith(::semVerComparator)
|
||||||
|
|
||||||
|
println("Project ${it.name}: last tag = $lastTag")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun httpGet(url: String): String = URI.create(url).toURL().readText()
|
||||||
|
|
||||||
|
fun semVerComparator(a: String, b: String): Int {
|
||||||
|
val aParts = a.split('.').map(String::toInt)
|
||||||
|
val bParts = b.split('.').map(String::toInt)
|
||||||
|
for (i in 0..2) {
|
||||||
|
if (aParts[i] > bParts[i]) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if (aParts[i] < bParts[i]) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Project(val id: Int, val name: String)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Tag(val name: String, val message: String)
|
Loading…
Reference in New Issue
Block a user