Skip to content

Commit

Permalink
example city game
Browse files Browse the repository at this point in the history
  • Loading branch information
Данила Беляков authored and Данила Беляков committed Aug 4, 2024
1 parent 95e58f8 commit fda6514
Show file tree
Hide file tree
Showing 5 changed files with 1,281 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.github.examples.cities

import com.github.alice.ktx.dispatch
import com.github.alice.ktx.handlers.message
import com.github.alice.ktx.middleware.outerMiddleware
import com.github.alice.ktx.models.response.response
import com.github.alice.ktx.server.impl.ktorWebServer
import com.github.alice.ktx.skill
import com.github.examples.cities.data.CitiesGameService

private enum class RegisterUserState {
INPUT_FIST_NAME
}

fun main() {

val citiesGameService = CitiesGameService()

skill {
id = "..."
webServer = ktorWebServer {
port = 8080
path = "/alice"
}
dispatch {

outerMiddleware {
if(message.session.user == null) {
return@outerMiddleware response {
text = "У вас нет аккаунта в Яндексе."
}
}
null
}

message({ message.session.new }) {
val userId = message.session.user!!.userId
val isUserExisting = citiesGameService.isUserExisting(userId)
if(!isUserExisting) {
state.setState(RegisterUserState.INPUT_FIST_NAME.name)
response { text = "Как тебя зовут?" }
}else {
response { text = citiesGameService.startGame(userId).name }
}
}

message({ state == RegisterUserState.INPUT_FIST_NAME.name }) {
val userId = message.session.user!!.userId
val firstName = message.request.originalUtterance!!
citiesGameService.createUser(id = userId, firstName = firstName)
state.clear()
response { text = citiesGameService.startGame(userId).name }
}

message {
val userId = message.session.user!!.userId
val cityName = message.request.command!!
response {
text = citiesGameService.processUserAnswer(userId, cityName)
}
}
}
}.run()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.github.examples.cities.data

import com.github.examples.cities.data.models.City
import com.github.examples.cities.data.models.User
import java.io.File

class CitiesGameService {

private val users = mutableMapOf<String, User>()
private val currentCityForUser = mutableMapOf<String, City>()
private val unusedCitiesForUser = mutableMapOf<String, MutableList<City>>()
private val allCities = mutableListOf<City>()

init {
/**
* Cities [Source](https://github.com/queenofpigeons/SQL_lab/blob/main/Список%20городов%20России.txt)
* */
val citiesFile = File("examples/src/main/resources/cities.txt")
citiesFile.readLines().forEach { line ->
val city = City(name = line)
allCities.add(city)
}
}

fun isUserExisting(id: String): Boolean {
return users.containsKey(id)
}

fun createUser(id: String, firstName: String) {
val user = User(id = id, firstName = firstName)
users[id] = user
}

fun startGame(userId: String): City {
val city = allCities.random()
currentCityForUser[userId] = city

val unusedCities = mutableListOf<City>().apply {
addAll(allCities)
remove(city)
}
unusedCitiesForUser[userId] = unusedCities

return city
}

fun processUserAnswer(userId: String, cityName: String): String {
val city = allCities.firstOrNull { it.name.equals(cityName.trim(), ignoreCase = true) }
if (city == null) return "Я не знаю такого города."

val currentCity = currentCityForUser[userId]!!
val lastChar = getEffectiveLastChar(currentCity.name)
val unusedCities = unusedCitiesForUser[userId]!!

return when {
!unusedCities.contains(city) -> "Такой город уже был."
cityName.first().lowercaseChar() != lastChar -> "Город должен начинаться на букву '$lastChar'."
else -> generateNextCity(userId, city)
}
}

private fun generateNextCity(userId: String, city: City): String {
val unusedCities = unusedCitiesForUser[userId]!!
unusedCities.remove(city)

val lastChar = getEffectiveLastChar(city.name)
val nextCity = unusedCities.firstOrNull { it.name.first().lowercaseChar() == lastChar }

return if (nextCity == null) {
"Поздравляю, вы победили! Начинаем заново: ${startGame(userId).name}."
} else {
unusedCities.remove(nextCity)
currentCityForUser[userId] = nextCity
nextCity.name
}
}

private fun getEffectiveLastChar(cityName: String): Char {
val trimmedName = cityName.trim().lowercase()
return when (val lastChar = trimmedName.last()) {
'ь', 'ъ', 'ы', 'й' -> trimmedName[trimmedName.length - 2]
else -> lastChar
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.github.examples.cities.data.models

data class City(
val name: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.github.examples.cities.data.models

data class User(
val id: String,
val firstName: String
)
Loading

0 comments on commit fda6514

Please sign in to comment.