Skip to content

Commit d47dcbf

Browse files
authored
release: 2.4.1 (#429)
2 parents 074394e + 269a0f8 commit d47dcbf

File tree

16 files changed

+290
-27
lines changed

16 files changed

+290
-27
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.gitanimals.core
2+
3+
4+
data class PersonaEvolution(
5+
val weight: Double,
6+
val type: PersonaEvolutionType,
7+
) {
8+
9+
companion object {
10+
11+
val nothing = PersonaEvolution(
12+
weight = 0.0,
13+
type = PersonaEvolutionType.NOTHING,
14+
)
15+
}
16+
}
17+
18+
enum class PersonaEvolutionType {
19+
20+
NOTHING,
21+
RABBIT,
22+
;
23+
}

src/main/kotlin/org/gitanimals/core/PersonaType.kt

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import kotlin.random.Random
99
enum class PersonaType(
1010
val weight: Double,
1111
val grade: PersonaGrade = PersonaGrade.DEFAULT,
12+
val personaEvolution: PersonaEvolution = PersonaEvolution.nothing,
1213
private var dropRate: String? = null,
1314
) {
1415
GOOSE(1.0) {
@@ -1510,7 +1511,7 @@ enum class PersonaType(
15101511
StringBuilder().moveRandomly("mole", id, 40, "180s", 5, 14.0)
15111512
.toString()
15121513
},
1513-
RABBIT(0.9) {
1514+
RABBIT(weight =0.9, personaEvolution = PersonaEvolution(weight = 0.001, PersonaEvolutionType.RABBIT)) {
15141515
override fun loadSvg(name: String, animationId: Long, level: Long, mode: Mode): String {
15151516
return rabbitSvg.replace("*{act}", act(animationId))
15161517
.replace("*{id}", animationId.toString())
@@ -1530,7 +1531,7 @@ enum class PersonaType(
15301531
StringBuilder().moveRandomly("rabbit", id, 40, "180s", 5, 10.0)
15311532
.toString()
15321533
},
1533-
RABBIT_BROWN_RUDOLPH(0.007) {
1534+
RABBIT_BROWN_RUDOLPH(weight = 0.007, personaEvolution = PersonaEvolution(weight = 0.01, PersonaEvolutionType.RABBIT)) {
15341535
override fun loadSvg(name: String, animationId: Long, level: Long, mode: Mode): String {
15351536
return rabbitBrownRudolphSvg.replace("*{act}", act(animationId))
15361537
.replace("*{id}", animationId.toString())
@@ -1570,7 +1571,7 @@ enum class PersonaType(
15701571
StringBuilder().moveRandomly("rabbit", id, 40, "180s", 5, 10.0)
15711572
.toString()
15721573
},
1573-
RABBIT_TUBE(0.01) {
1574+
RABBIT_TUBE(weight = 0.01, personaEvolution = PersonaEvolution(weight = 0.02, PersonaEvolutionType.RABBIT)) {
15741575
override fun loadSvg(name: String, animationId: Long, level: Long, mode: Mode): String {
15751576
return rabbitTubeSvg.replace("*{act}", act(animationId))
15761577
.replace("*{id}", animationId.toString())
@@ -2352,6 +2353,14 @@ enum class PersonaType(
23522353
}
23532354
}
23542355

2356+
fun randomEvolution(): PersonaType {
2357+
val evolutionCandidates = personasPerEvolutionType[personaEvolution.type]
2358+
require(evolutionCandidates.isNullOrEmpty().not()) {
2359+
"Cannot find evolution candidates. personaType: ${this.name}, evolutionType: ${this.personaEvolution.type}"
2360+
}
2361+
return evolutionCandidates!!.random()
2362+
}
2363+
23552364
companion object {
23562365
private val dropRateFormat = DecimalFormat("#.##")
23572366

@@ -2373,6 +2382,30 @@ enum class PersonaType(
23732382
weightedPersonas.shuffled()
23742383
}.value
23752384

2385+
private val personasPerEvolutionType: Map<PersonaEvolutionType, List<PersonaType>> = lazy {
2386+
val weightedEvolutionPersonas = PersonaEvolutionType.entries.filterNot {
2387+
it == PersonaEvolutionType.NOTHING
2388+
}.associateWith { mutableListOf<PersonaType>() }
2389+
2390+
entries.filterNot {
2391+
it.personaEvolution == PersonaEvolution.nothing
2392+
}.forEach { personaType ->
2393+
val personaTypes = weightedEvolutionPersonas.getOrElse(personaType.personaEvolution.type) {
2394+
mutableListOf()
2395+
}
2396+
2397+
repeat((personaType.personaEvolution.weight * 1000).toInt()) {
2398+
personaTypes.add(personaType)
2399+
}
2400+
}
2401+
2402+
weightedEvolutionPersonas.forEach { (_, value) ->
2403+
value.shuffle()
2404+
}
2405+
2406+
weightedEvolutionPersonas
2407+
}.value
2408+
23762409
fun random(): PersonaType = personas[Random.nextInt(0, maxWeight)]
23772410

23782411
private fun StringBuilder.moveRandomly(

src/main/kotlin/org/gitanimals/render/app/IdentityApi.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ interface IdentityApi {
1919
@RequestParam("idempotency-key") idempotencyKey: String,
2020
)
2121

22+
@GetExchange("/internals/users/{user-id}")
23+
fun getUserById(
24+
@PathVariable("user-id") userId: Long
25+
): UserResponse
26+
2227
data class UserResponse(
2328
val id: String,
2429
val username: String,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.gitanimals.render.app
2+
3+
import org.gitanimals.render.domain.UserService
4+
import org.gitanimals.render.domain.response.PersonaResponse
5+
import org.springframework.stereotype.Service
6+
7+
@Service
8+
class PersonaEvolutionFacade(
9+
private val identityApi: IdentityApi,
10+
private val userService: UserService,
11+
) {
12+
13+
fun evolutionPersona(token: String, personaId: Long): PersonaResponse {
14+
val user = identityApi.getUserByToken(token)
15+
16+
return userService.evolutionPersona(
17+
name = user.username,
18+
personaId = personaId,
19+
)
20+
}
21+
22+
fun isEvoluationable(token: String, personaId: Long): Boolean {
23+
val user = identityApi.getUserByToken(token)
24+
25+
return userService.isEvoluationable(
26+
name = user.username,
27+
personaId = personaId,
28+
)
29+
}
30+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.gitanimals.render.controller
2+
3+
import org.gitanimals.core.auth.RequiredUserEntryPoints
4+
import org.gitanimals.core.auth.UserEntryPoint
5+
import org.gitanimals.render.app.PersonaEvolutionFacade
6+
import org.gitanimals.render.controller.response.PersonaEvolutionableResponse
7+
import org.gitanimals.render.controller.response.PersonaResponse
8+
import org.springframework.http.HttpHeaders
9+
import org.springframework.http.HttpStatus
10+
import org.springframework.web.bind.annotation.*
11+
12+
@RestController
13+
class PersonaEvolutionController(
14+
private val personaEvolutionFacade: PersonaEvolutionFacade,
15+
) {
16+
17+
@PostMapping("/personas/{personaId}/evolution")
18+
@ResponseStatus(HttpStatus.OK)
19+
@RequiredUserEntryPoints([UserEntryPoint.GITHUB])
20+
fun evolutionPersona(
21+
@RequestHeader(HttpHeaders.AUTHORIZATION) token: String,
22+
@PathVariable personaId: Long,
23+
): PersonaResponse {
24+
return PersonaResponse.from(
25+
personaEvolutionFacade.evolutionPersona(
26+
token = token,
27+
personaId = personaId,
28+
)
29+
)
30+
}
31+
32+
@GetMapping("/personas/{personaId}/evolution")
33+
@ResponseStatus(HttpStatus.OK)
34+
@RequiredUserEntryPoints([UserEntryPoint.GITHUB])
35+
fun isEvolutionablePersona(
36+
@RequestHeader(HttpHeaders.AUTHORIZATION) token: String,
37+
@PathVariable personaId: Long,
38+
): PersonaEvolutionableResponse {
39+
return PersonaEvolutionableResponse(
40+
evolutionAble = personaEvolutionFacade.isEvoluationable(
41+
token = token,
42+
personaId = personaId,
43+
)
44+
)
45+
}
46+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.gitanimals.render.controller.response
2+
3+
data class PersonaEvolutionableResponse(
4+
val evolutionAble: Boolean
5+
)

src/main/kotlin/org/gitanimals/render/controller/response/UserResponse.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ data class UserResponse(
1818
user.personas.map {
1919
PersonaResponse(
2020
id = it.id.toString(),
21-
type = it.type,
21+
type = it.getType(),
2222
level = it.level().toString(),
2323
visible = it.visible,
2424
appVisible = it.appVisible,
25-
dropRate = it.type.getDropRate(),
26-
grade = it.type.grade,
25+
dropRate = it.getType().getDropRate(),
26+
grade = it.getType().grade,
2727
)
2828
}.toList()
2929
)
@@ -39,12 +39,12 @@ data class UserResponse(
3939
}.map {
4040
PersonaResponse(
4141
id = it.id.toString(),
42-
type = it.type,
42+
type = it.getType(),
4343
level = it.level().toString(),
4444
visible = it.visible,
4545
appVisible = it.appVisible,
46-
dropRate = it.type.getDropRate(),
47-
grade = it.type.grade,
46+
dropRate = it.getType().getDropRate(),
47+
grade = it.getType().grade,
4848
)
4949
}.toList()
5050
)
@@ -60,12 +60,12 @@ data class UserResponse(
6060
.let {
6161
PersonaResponse(
6262
id = it.id.toString(),
63-
type = it.type,
63+
type = it.getType(),
6464
level = it.level().toString(),
6565
visible = it.visible,
6666
appVisible = it.appVisible,
67-
dropRate = it.type.getDropRate(),
68-
grade = it.type.grade,
67+
dropRate = it.getType().getDropRate(),
68+
grade = it.getType().grade,
6969
)
7070
}
7171
)

src/main/kotlin/org/gitanimals/render/domain/Persona.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore
44
import jakarta.persistence.*
55
import org.gitanimals.core.IdGenerator
66
import org.gitanimals.core.Mode
7+
import org.gitanimals.core.PersonaEvolution
78
import org.gitanimals.core.PersonaType
89
import org.gitanimals.render.domain.value.Level
910

@@ -16,7 +17,7 @@ class Persona(
1617

1718
@Column(name = "type", nullable = false, columnDefinition = "TEXT")
1819
@Enumerated(EnumType.STRING)
19-
val type: PersonaType,
20+
private var type: PersonaType,
2021

2122
@Embedded
2223
val level: Level,
@@ -56,6 +57,7 @@ class Persona(
5657
user = user
5758
)
5859

60+
fun getType() = this.type
5961

6062
fun toSvgForce(mode: Mode): String = type.load(
6163
name = user!!.getName(),
@@ -80,4 +82,14 @@ class Persona(
8082
}
8183

8284
fun level(): Long = level.value
85+
86+
fun evolution() {
87+
require (type.personaEvolution != PersonaEvolution.nothing) {
88+
"Evolution fail cause, not support evolution type :${type.name}"
89+
}
90+
91+
val evolutionedPersonaType = this.type.randomEvolution()
92+
this.type = evolutionedPersonaType
93+
this.level.value = 0
94+
}
8395
}

src/main/kotlin/org/gitanimals/render/domain/PersonaStatisticService.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ class PersonaStatisticService(
2525
}
2626

2727
personas.content.forEach {
28-
newPetDropRateDistributionMap.getOrPut(it.type.weight) { 0 }
29-
newPetDropRateDistributionMap[it.type.weight] = (newPetDropRateDistributionMap[it.type.weight] ?: 0) + 1
28+
newPetDropRateDistributionMap.getOrPut(it.getType().weight) { 0 }
29+
newPetDropRateDistributionMap[it.getType().weight] = (newPetDropRateDistributionMap[it.getType().weight] ?: 0) + 1
3030
}
3131

3232
while (personas.hasNext()) {
3333
pageable = pageable.next()
3434
personas = personaStatisticRepository.findAllPersonaByCreatedAtAfter(createdAt, pageable)
3535
personas.content.forEach {
36-
newPetDropRateDistributionMap.getOrPut(it.type.weight) { 0 }
37-
newPetDropRateDistributionMap[it.type.weight] = (newPetDropRateDistributionMap[it.type.weight] ?: 0) + 1
36+
newPetDropRateDistributionMap.getOrPut(it.getType().weight) { 0 }
37+
newPetDropRateDistributionMap[it.getType().weight] = (newPetDropRateDistributionMap[it.getType().weight] ?: 0) + 1
3838
}
3939
}
4040

src/main/kotlin/org/gitanimals/render/domain/User.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,12 +340,35 @@ class User(
340340
.append("</svg>")
341341
.toString()
342342

343+
fun evolution(personaId: Long): Persona {
344+
val persona = personas.firstOrNull {
345+
it.id == personaId
346+
} ?: throw IllegalArgumentException("Cannot evolution persona cause cannot find matched persona by id: \"$personaId\"")
347+
348+
require(persona.level() >= EVOLUTION_REQUIRED_LEVEL) {
349+
"Cannot evolution persona cause, ${persona.level()} is not enough level for evolution."
350+
}
351+
352+
persona.evolution()
353+
return persona
354+
}
355+
356+
fun isEvolutionable(personaId: Long): Boolean {
357+
val persona = personas.firstOrNull {
358+
it.id == personaId
359+
} ?: throw IllegalArgumentException("Cannot evolution persona cause cannot find matched persona by id: \"$personaId\"")
360+
361+
return persona.level() >= EVOLUTION_REQUIRED_LEVEL && persona.getType().personaEvolution != PersonaEvolution.nothing
362+
}
363+
343364
companion object {
344365
private const val MAX_PERSONA_COUNT = 30L
345366
private const val MAX_INIT_PERSONA_COUNT = 10L
346367
private const val FOR_NEW_PERSONA_COUNT = 30L
347368
private const val FOR_INIT_PERSONA_COUNT = 100L
348369

370+
private const val EVOLUTION_REQUIRED_LEVEL = 100L
371+
349372
private val nameConvention = Regex("[^a-zA-Z0-9-]")
350373

351374
private val logger = LoggerFactory.getLogger(this::class.simpleName)

0 commit comments

Comments
 (0)