diff --git a/README.md b/README.md
index be1a20d..ce7872b 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
##
-
+
⭐스타를 눌러주세요 개발에 큰 도움이 됩니다!⭐️
@@ -39,29 +39,31 @@
line mode는 자신이 갖고있는 펫중 하나를 지정해서, 지정한 width, height범위에서 움직이게 해요.
line mode를 사용할때, markdown 방식으로 이미지를 요청하면, width, height를 설정할 수 없어서 펫이 보이지 않을 수 있으니, HTMl방식을
사용해주세요.
-_pet-id에 아무값도 입력하지 않으면, 첫번째 펫이 가져와져요._
-
-변경 가능한 pet-id는 `https://render.gitanimals.org/users/{username}` 의 {username}을 자신의 깃허브 아이디로 변경 후 API를 요청하면 확인할 수 있어요.
-API 응답의 `$.personas.[].id` 에 해당하는 값을 pet-id에 입력하면 돼요.
> [!TIP]
> **Img의 width와 height를 조절해서 펫의 이동영역을 조절할 수 있어요.**
> width를 길게 height를 작게하면 (width = 1000, height = 60) 가로로 길게 움직이게 할 수 있어요.
> 반대로, width를 작게 height를 길게하면 (width = 60, height = 1000) 세로로 길게 움직이게 할 수 있어요.
-> img의 height를 펫의 세로 길이보다 충분히 크게 적용해주세요. 그러지 않으면 펫이 숨어버려요.
+> 만약, 펫이 보이지 않는다면, img의 height를 펫의 세로 길이보다 충분히 크게 적용해주세요.
+
-**html**
-
```html
```
+_pet-id에 아무값도 입력하지 않으면, 첫번째 펫이 가져와져요._
+
+변경 가능한 pet-id는 `https://render.gitanimals.org/users/{username}` 의 {username}을 자신의 깃허브 아이디로 변경 후 API를 요청하면 확인할 수 있어요.
+API 응답의 `$.personas.[].id` 에 해당하는 값을 pet-id에 입력하면 돼요.
+
+lines모드에서는 펫 레벨 위에 총 contributions수를 보여줘요. 원하지 않을경우, 쿼리 파라미터로 `contribution-view=false`를 담아 요청하세요.
+
### farm mode
farm mode는 갖고있는 모든 동물과 추가적인 정보를 보여줘요.
diff --git a/gradle.properties b/gradle.properties
index 91ef374..3370ffa 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -28,3 +28,9 @@ netxVersion=0.4.2
### Sentry ###
sentryVersion=4.4.0
+
+### RestAssured ###
+restAssuredVersion=5.4.0
+
+### H2version ###
+h2Version=1.4.200
diff --git a/gradle/db.gradle b/gradle/db.gradle
index 7d7afdc..61d4ab8 100644
--- a/gradle/db.gradle
+++ b/gradle/db.gradle
@@ -1,5 +1,5 @@
dependencies {
implementation "mysql:mysql-connector-java:${mysqlConnectorVersion}"
- testRuntimeOnly "com.h2database:h2"
+ testRuntimeOnly "com.h2database:h2:${h2Version}"
}
diff --git a/gradle/test.gradle b/gradle/test.gradle
index 60b80e1..bf9f2e1 100644
--- a/gradle/test.gradle
+++ b/gradle/test.gradle
@@ -8,4 +8,7 @@ dependencies {
testImplementation "io.kotest.extensions:kotest-extensions-spring:${kotestExtensionSpringVersion}"
testImplementation "org.testcontainers:testcontainers:${testContainerVersion}"
+
+ testImplementation "io.rest-assured:rest-assured:${restAssuredVersion}"
+
}
diff --git a/src/main/kotlin/org/gitanimals/render/app/AnimationFacade.kt b/src/main/kotlin/org/gitanimals/render/app/AnimationFacade.kt
index fd5d15d..3af8dae 100644
--- a/src/main/kotlin/org/gitanimals/render/app/AnimationFacade.kt
+++ b/src/main/kotlin/org/gitanimals/render/app/AnimationFacade.kt
@@ -1,5 +1,6 @@
package org.gitanimals.render.app
+import org.gitanimals.render.domain.Mode
import org.gitanimals.render.domain.User
import org.gitanimals.render.domain.UserService
import org.gitanimals.render.domain.event.Visited
@@ -29,17 +30,17 @@ class AnimationFacade(
}
}
- fun getLineAnimation(username: String, personaId: Long): String {
+ fun getLineAnimation(username: String, personaId: Long, mode: Mode): String {
return when (userService.existsByName(username)) {
true -> {
- val svgAnimation = userService.getLineAnimationByUsername(username, personaId)
+ val svgAnimation = userService.getLineAnimationByUsername(username, personaId, mode)
sagaManager.startSync(Visited(username))
svgAnimation
}
false -> {
val user = createNewUser(username)
- userService.getLineAnimationByUsername(user.name, personaId)
+ userService.getLineAnimationByUsername(user.name, personaId, mode)
}
}
}
diff --git a/src/main/kotlin/org/gitanimals/render/controller/AnimationController.kt b/src/main/kotlin/org/gitanimals/render/controller/AnimationController.kt
index 0fd4e2d..4b3cd59 100644
--- a/src/main/kotlin/org/gitanimals/render/controller/AnimationController.kt
+++ b/src/main/kotlin/org/gitanimals/render/controller/AnimationController.kt
@@ -2,6 +2,7 @@ package org.gitanimals.render.controller
import jakarta.servlet.http.HttpServletResponse
import org.gitanimals.render.app.AnimationFacade
+import org.gitanimals.render.domain.Mode
import org.springframework.http.HttpHeaders
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
@@ -26,10 +27,17 @@ class AnimationController(
fun getLineSvgAnimation(
@PathVariable("username") username: String,
@RequestParam(name = "pet-id", defaultValue = "0") personaId: Long,
+ @RequestParam(name = "contribution-view", defaultValue = "true") contributionView: Boolean,
response: HttpServletResponse,
): String {
response.cacheControl(3600)
- return animationFacade.getLineAnimation(deleteBrackets(username), personaId)
+
+ val mode = when (contributionView) {
+ true -> Mode.LINE
+ false -> Mode.LINE_NO_CONTRIBUTION
+ }
+
+ return animationFacade.getLineAnimation(deleteBrackets(username), personaId, mode)
}
private fun deleteBrackets(username: String): String {
diff --git a/src/main/kotlin/org/gitanimals/render/controller/filter/CorsFilter.kt b/src/main/kotlin/org/gitanimals/render/controller/filter/CorsFilter.kt
new file mode 100644
index 0000000..4165d18
--- /dev/null
+++ b/src/main/kotlin/org/gitanimals/render/controller/filter/CorsFilter.kt
@@ -0,0 +1,41 @@
+package org.gitanimals.render.controller.filter
+
+import jakarta.servlet.Filter
+import jakarta.servlet.FilterChain
+import jakarta.servlet.ServletRequest
+import jakarta.servlet.ServletResponse
+import jakarta.servlet.http.HttpServletRequest
+import jakarta.servlet.http.HttpServletResponse
+import org.springframework.http.HttpHeaders
+import org.springframework.stereotype.Component
+
+@Component
+class CorsFilter : Filter {
+
+ override fun doFilter(
+ request: ServletRequest,
+ response: ServletResponse,
+ chain: FilterChain
+ ) {
+ (request as HttpServletRequest)
+ if (regexMatcher.matches(request.requestURI)) {
+ (response as HttpServletResponse).allowCors()
+ }
+ chain.doFilter(request, response)
+ }
+
+ private fun HttpServletResponse.allowCors(): ServletResponse {
+ this.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*")
+ this.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "*")
+ this.addHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3600")
+ this.addHeader(
+ HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,
+ "Origin, X-Requested-With, Content-Type, Accept, Authorization"
+ )
+ return this
+ }
+
+ private companion object {
+ private val regexMatcher = Regex("/users/.*")
+ }
+}
diff --git a/src/main/kotlin/org/gitanimals/render/domain/Mode.kt b/src/main/kotlin/org/gitanimals/render/domain/Mode.kt
new file mode 100644
index 0000000..4c08dfe
--- /dev/null
+++ b/src/main/kotlin/org/gitanimals/render/domain/Mode.kt
@@ -0,0 +1,8 @@
+package org.gitanimals.render.domain
+
+enum class Mode {
+ FARM,
+ LINE,
+ LINE_NO_CONTRIBUTION,
+ ;
+}
diff --git a/src/main/kotlin/org/gitanimals/render/domain/Persona.kt b/src/main/kotlin/org/gitanimals/render/domain/Persona.kt
index 7f90b2d..5ddad62 100644
--- a/src/main/kotlin/org/gitanimals/render/domain/Persona.kt
+++ b/src/main/kotlin/org/gitanimals/render/domain/Persona.kt
@@ -35,13 +35,13 @@ class Persona(
) : this(type = type, level = Level(level), visible = visible)
- fun toSvgForce(): String = type.load(this)
+ fun toSvgForce(mode: Mode): String = type.load(user!!, this, mode)
- fun toSvg(): String {
+ fun toSvg(mode: Mode): String {
if (!visible) {
return ""
}
- return type.load(this)
+ return type.load(user!!, this, mode)
}
fun level(): Long = level.value
diff --git a/src/main/kotlin/org/gitanimals/render/domain/PersonaType.kt b/src/main/kotlin/org/gitanimals/render/domain/PersonaType.kt
index ea5ac10..f88adb6 100644
--- a/src/main/kotlin/org/gitanimals/render/domain/PersonaType.kt
+++ b/src/main/kotlin/org/gitanimals/render/domain/PersonaType.kt
@@ -7,7 +7,7 @@ import kotlin.random.Random
enum class PersonaType(private val weight: Double) {
GOOSE(1.0) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val goose = gooseSvg.replace("*{act}", act(persona.id))
@@ -30,7 +30,7 @@ enum class PersonaType(private val weight: Double) {
},
GOOSE_SUNGLASSES(0.05) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val goose = gooseSunglassesSvg.replace("*{act}", act(persona.id))
@@ -53,7 +53,7 @@ enum class PersonaType(private val weight: Double) {
},
GOOSE_KOTLIN(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val goose = gooseKotlinSvg.replace("*{act}", act(persona.id))
@@ -76,7 +76,7 @@ enum class PersonaType(private val weight: Double) {
},
GOOSE_JAVA(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val goose = gooseJavaSvg.replace("*{act}", act(persona.id))
@@ -99,7 +99,7 @@ enum class PersonaType(private val weight: Double) {
},
GOOSE_JS(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val goose = gooseJsSvg.replace("*{act}", act(persona.id))
@@ -122,7 +122,7 @@ enum class PersonaType(private val weight: Double) {
},
GOOSE_NODE(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val goose = gooseNodeSvg.replace("*{act}", act(persona.id))
@@ -145,7 +145,7 @@ enum class PersonaType(private val weight: Double) {
},
GOOSE_SWIFT(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val goose = gooseSwiftSvg.replace("*{act}", act(persona.id))
@@ -168,7 +168,7 @@ enum class PersonaType(private val weight: Double) {
},
GOOSE_LINUX(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val goose = gooseLinuxSvg.replace("*{act}", act(persona.id))
@@ -191,7 +191,7 @@ enum class PersonaType(private val weight: Double) {
},
GOOSE_SPRING(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val goose = gooseSpringSvg.replace("*{act}", act(persona.id))
@@ -214,7 +214,7 @@ enum class PersonaType(private val weight: Double) {
},
LITTLE_CHICK(0.9) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val littleChick = littleChickSvg.replace("*{act}", act(persona.id))
@@ -237,7 +237,7 @@ enum class PersonaType(private val weight: Double) {
},
LITTLE_CHICK_SUNGLASSES(0.4) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val littleChick = littleChickSunglassesSvg.replace("*{act}", act(persona.id))
@@ -260,7 +260,7 @@ enum class PersonaType(private val weight: Double) {
},
LITTLE_CHICK_KOTLIN(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val littleChick = littleChickKotlinSvg.replace("*{act}", act(persona.id))
@@ -283,7 +283,7 @@ enum class PersonaType(private val weight: Double) {
},
LITTLE_CHICK_JAVA(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val littleChick = littleChickJavaSvg.replace("*{act}", act(persona.id))
@@ -306,7 +306,7 @@ enum class PersonaType(private val weight: Double) {
},
LITTLE_CHICK_JS(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val littleChick = littleChickJsSvg.replace("*{act}", act(persona.id))
@@ -329,7 +329,7 @@ enum class PersonaType(private val weight: Double) {
},
LITTLE_CHICK_NODE(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val littleChick = littleChickNodeSvg.replace("*{act}", act(persona.id))
@@ -352,7 +352,7 @@ enum class PersonaType(private val weight: Double) {
},
LITTLE_CHICK_SWIFT(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val littleChick = littleChickSwiftSvg.replace("*{act}", act(persona.id))
@@ -375,7 +375,7 @@ enum class PersonaType(private val weight: Double) {
},
LITTLE_CHICK_LINUX(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val littleChick = littleChickLinuxSvg.replace("*{act}", act(persona.id))
@@ -398,7 +398,7 @@ enum class PersonaType(private val weight: Double) {
},
LITTLE_CHICK_SPRING(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
val littleChick = littleChickSpringSvg.replace("*{act}", act(persona.id))
@@ -421,7 +421,7 @@ enum class PersonaType(private val weight: Double) {
},
PENGUIN(0.5) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return penguinSvg.replace("*{act}", act(persona.id))
@@ -440,7 +440,7 @@ enum class PersonaType(private val weight: Double) {
},
PENGUIN_SUNGLASSES(0.2) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return penguinSunglassesSvg.replace("*{act}", act(persona.id))
@@ -459,7 +459,7 @@ enum class PersonaType(private val weight: Double) {
},
PENGUIN_KOTLIN(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return penguinKotlinSvg.replace("*{act}", act(persona.id))
@@ -478,7 +478,7 @@ enum class PersonaType(private val weight: Double) {
},
PENGUIN_JAVA(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return penguinJavaSvg.replace("*{act}", act(persona.id))
@@ -497,7 +497,7 @@ enum class PersonaType(private val weight: Double) {
},
PENGUIN_JS(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return penguinJsSvg.replace("*{act}", act(persona.id))
@@ -516,7 +516,7 @@ enum class PersonaType(private val weight: Double) {
},
PENGUIN_NODE(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return penguinNodeSvg.replace("*{act}", act(persona.id))
@@ -535,7 +535,7 @@ enum class PersonaType(private val weight: Double) {
},
PENGUIN_SWIFT(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return penguinSwiftSvg.replace("*{act}", act(persona.id))
@@ -554,7 +554,7 @@ enum class PersonaType(private val weight: Double) {
},
PENGUIN_LINUX(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return penguinLinuxSvg.replace("*{act}", act(persona.id))
@@ -573,7 +573,7 @@ enum class PersonaType(private val weight: Double) {
},
PENGUIN_SPRING(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return penguinSpringSvg.replace("*{act}", act(persona.id))
@@ -592,7 +592,7 @@ enum class PersonaType(private val weight: Double) {
},
PIG(0.2) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return pigSvg.replace("*{act}", act(persona.id))
@@ -610,7 +610,7 @@ enum class PersonaType(private val weight: Double) {
},
PIG_SUNGLASSES(0.08) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return pigSunglassesSvg.replace("*{act}", act(persona.id))
@@ -628,7 +628,7 @@ enum class PersonaType(private val weight: Double) {
},
PIG_KOTLIN(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return pigKotlinSvg.replace("*{act}", act(persona.id))
@@ -646,7 +646,7 @@ enum class PersonaType(private val weight: Double) {
},
PIG_JAVA(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return pigJavaSvg.replace("*{act}", act(persona.id))
@@ -664,7 +664,7 @@ enum class PersonaType(private val weight: Double) {
},
PIG_JS(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return pigJsSvg.replace("*{act}", act(persona.id))
@@ -682,7 +682,7 @@ enum class PersonaType(private val weight: Double) {
},
PIG_NODE(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return pigNodeSvg.replace("*{act}", act(persona.id))
@@ -700,7 +700,7 @@ enum class PersonaType(private val weight: Double) {
},
PIG_SWIFT(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return pigSwiftSvg.replace("*{act}", act(persona.id))
@@ -718,7 +718,7 @@ enum class PersonaType(private val weight: Double) {
},
PIG_LINUX(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return pigLinuxSvg.replace("*{act}", act(persona.id))
@@ -736,7 +736,7 @@ enum class PersonaType(private val weight: Double) {
},
PIG_SPRING(0.01) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return pigSpringSvg.replace("*{act}", act(persona.id))
@@ -754,7 +754,7 @@ enum class PersonaType(private val weight: Double) {
},
SLIME_RED(0.1) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return slimeRedSvg.replace("*{act}", act(persona.id))
@@ -772,7 +772,7 @@ enum class PersonaType(private val weight: Double) {
},
SLIME_RED_KOTLIN(0.001) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return slimeRedKotlinSvg.replace("*{act}", act(persona.id))
@@ -790,7 +790,7 @@ enum class PersonaType(private val weight: Double) {
},
SLIME_RED_JAVA(0.001) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return slimeRedJavaSvg.replace("*{act}", act(persona.id))
@@ -808,7 +808,7 @@ enum class PersonaType(private val weight: Double) {
},
SLIME_RED_JS(0.001) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return slimeRedJsSvg.replace("*{act}", act(persona.id))
@@ -826,7 +826,7 @@ enum class PersonaType(private val weight: Double) {
},
SLIME_RED_NODE(0.001) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return slimeRedNodeSvg.replace("*{act}", act(persona.id))
@@ -844,7 +844,7 @@ enum class PersonaType(private val weight: Double) {
},
SLIME_RED_SWIFT(0.001) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return slimeRedSwiftSvg.replace("*{act}", act(persona.id))
@@ -862,7 +862,7 @@ enum class PersonaType(private val weight: Double) {
},
SLIME_RED_LINUX(0.001) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return slimeRedLinuxSvg.replace("*{act}", act(persona.id))
@@ -880,7 +880,7 @@ enum class PersonaType(private val weight: Double) {
},
SLIME_BLUE(0.1) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return slimeBlueSvg.replace("*{act}", act(persona.id))
@@ -898,7 +898,7 @@ enum class PersonaType(private val weight: Double) {
},
SLIME_GREEN(0.1) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return slimeGreenSvg.replace("*{act}", act(persona.id))
@@ -916,7 +916,7 @@ enum class PersonaType(private val weight: Double) {
},
FLAMINGO(0.05) {
- override fun load(persona: Persona): String {
+ override fun loadSvg(user: User, persona: Persona, mode: Mode): String {
check(persona.id != null) { "Save persona first before call load()" }
return flamingoSvg.replace("*{position}", act(persona.id))
@@ -944,10 +944,32 @@ enum class PersonaType(private val weight: Double) {
require(weight in 0.001..1.0) { "PersonaType's weight should be between 0.01 to 1.0" }
}
- abstract fun load(persona: Persona): String
+ fun load(user: User, persona: Persona, mode: Mode): String =
+ loadSvg(user, persona, mode)
+ .drawContribution(mode, user)
+
+ abstract fun loadSvg(user: User, persona: Persona, mode: Mode): String
protected abstract fun act(id: Long): String
+ protected fun String.drawContribution(
+ mode: Mode,
+ user: User
+ ): String {
+ return if (mode == Mode.LINE) {
+ this.replace(
+ "*{contributionx}",
+ (12 + (-1 * (user.contributionCount().toString().length))).toString()
+ )
+ .replace(
+ "*{contribution}",
+ user.contributionCount().toSvg(0.0, 2.0)
+ ).replace("*{contribution-display}", "default")
+ } else {
+ this.replace("*{contribution-display}", "none")
+ }
+ }
+
companion object {
private val maxWeight = lazy {
@@ -1040,15 +1062,19 @@ enum class PersonaType(private val weight: Double) {
}
private fun Long.toSvg(levelStartX: Double, xIncrease: Double): String {
+ return this.toSvgWithY(-1.0, levelStartX, xIncrease)
+ }
+
+ private fun Long.toSvgWithY(startY: Double, startX: Double, xIncrease: Double): String {
val level = this.toString()
- var currentX = levelStartX
+ var currentX = startX
val builder = StringBuilder()
level.withIndex().forEach {
val index = it.index
val number = it.value.digitToInt()
val numberSvg = numberSvgs[number]
- builder.append("
")
+ builder.append("")
.append(numberSvg)
.append("")
diff --git a/src/main/kotlin/org/gitanimals/render/domain/User.kt b/src/main/kotlin/org/gitanimals/render/domain/User.kt
index fd48946..ec87260 100644
--- a/src/main/kotlin/org/gitanimals/render/domain/User.kt
+++ b/src/main/kotlin/org/gitanimals/render/domain/User.kt
@@ -120,12 +120,12 @@ class User(
visit += 1
}
- fun createLineAnimation(personaId: Long): String {
+ fun createLineAnimation(personaId: Long, mode: Mode): String {
val builder = StringBuilder().openLine()
val persona = personas.find { it.id!! >= personaId }
?: throw IllegalArgumentException("Cannot find persona by id \"$personaId\"")
- builder.append(persona.toSvgForce())
+ builder.append(persona.toSvgForce(mode))
return builder.closeSvg()
}
@@ -139,13 +139,15 @@ class User(
.append(field.fillBackground())
personas.asSequence()
- .forEach { builder.append(it.toSvg()) }
+ .forEach { builder.append(it.toSvg(Mode.FARM)) }
return builder.append(field.loadComponent(name, contributions.totalCount()))
.append(field.drawBorder())
.closeSvg()
}
+ fun contributionCount(): Long = contributions.totalCount()
+
private fun List.totalCount(): Long {
var totalCount = 0L
this.forEach { totalCount += it.contribution }
diff --git a/src/main/kotlin/org/gitanimals/render/domain/UserService.kt b/src/main/kotlin/org/gitanimals/render/domain/UserService.kt
index 66df64e..006c315 100644
--- a/src/main/kotlin/org/gitanimals/render/domain/UserService.kt
+++ b/src/main/kotlin/org/gitanimals/render/domain/UserService.kt
@@ -17,8 +17,8 @@ class UserService(
return getUserByName(username).createFarmAnimation()
}
- fun getLineAnimationByUsername(username: String, personaId: Long): String {
- return getUserByName(username).createLineAnimation(personaId)
+ fun getLineAnimationByUsername(username: String, personaId: Long, mode: Mode): String {
+ return getUserByName(username).createLineAnimation(personaId, mode)
}
@Retryable(retryFor = [ObjectOptimisticLockingFailureException::class], maxAttempts = 10)
diff --git a/src/main/resources/persona/animal/flamingo.svg b/src/main/resources/persona/animal/flamingo.svg
index 60f0b67..1a22fe8 100644
--- a/src/main/resources/persona/animal/flamingo.svg
+++ b/src/main/resources/persona/animal/flamingo.svg
@@ -23,6 +23,17 @@
+
+
+
+