Skip to content

Commit

Permalink
Merge pull request #42 from freekode/tp-copy-workout
Browse files Browse the repository at this point in the history
Copy workouts
  • Loading branch information
freekode authored Mar 11, 2024
2 parents d25c346 + 1bd9857 commit 099b5fb
Show file tree
Hide file tree
Showing 60 changed files with 597 additions and 355 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package org.freekode.tp2intervals.app.plan
import org.freekode.tp2intervals.domain.Platform
import org.freekode.tp2intervals.domain.plan.Plan

data class CopyPlanRequest(
data class CopyLibraryRequest(
val plan: Plan,
val newName: String,
val sourcePlatform: Platform,
val targetPlatform: Platform,
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@ import org.freekode.tp2intervals.infrastructure.utils.Date
import org.springframework.stereotype.Service

@Service
class PlanService(
class LibraryService(
workoutRepositories: List<WorkoutRepository>,
planRepositories: List<PlanRepository>,
) {
private val workoutRepositoryMap = workoutRepositories.associateBy { it.platform() }
private val planRepositoryMap = planRepositories.associateBy { it.platform() }

fun getPlans(platform: Platform): List<Plan> {
fun getLibraries(platform: Platform): List<Plan> {
val repository = planRepositoryMap[platform]!!
return repository.getPlans()
return repository.getLibraries()
}

fun copyPlan(request: CopyPlanRequest): CopyPlanResponse {
fun copyLibrary(request: CopyLibraryRequest): CopyPlanResponse {
val targetPlanRepository = planRepositoryMap[request.targetPlatform]!!
val sourceWorkoutRepository = workoutRepositoryMap[request.sourcePlatform]!!
val targetWorkoutRepository = workoutRepositoryMap[request.targetPlatform]!!

val workouts = sourceWorkoutRepository.getWorkouts(request.plan)
val newPlan = targetPlanRepository.createPlan(request.plan.name, Date.thisMonday(), true)
workouts.forEach { targetWorkoutRepository.saveWorkout(it, newPlan) }
val workouts = sourceWorkoutRepository.getWorkoutsFromLibrary(request.plan)
val newPlan = targetPlanRepository.createPlan(request.newName, Date.thisMonday(), true)
workouts.forEach { targetWorkoutRepository.saveWorkoutToLibrary(it, newPlan) }
return CopyPlanResponse(newPlan.name, workouts.size)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.freekode.tp2intervals.app.schedule

import org.freekode.tp2intervals.app.workout.PlanWorkoutsRequest
import org.freekode.tp2intervals.app.workout.ScheduleWorkoutsRequest
import org.freekode.tp2intervals.app.workout.WorkoutService
import org.slf4j.LoggerFactory
import org.springframework.scheduling.annotation.Scheduled
Expand All @@ -15,9 +15,9 @@ class ScheduledJobs(

@Scheduled(cron = "#{planWorkoutsCron}")
fun planWorkouts() {
val planWorkoutsRequest = scheduleService.getScheduledRequest(PlanWorkoutsRequest::class.java) ?: return
val scheduleWorkoutsRequest = scheduleService.getScheduledRequest(ScheduleWorkoutsRequest::class.java) ?: return
log.info("Start scheduled workouts planning")
val response = workoutService.planWorkouts(planWorkoutsRequest)
val response = workoutService.copyPlannedWorkouts(scheduleWorkoutsRequest)
log.debug("Scheduled workouts planning, response: {}", response)
log.info("End scheduled workouts planning")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.time.LocalDate
import org.freekode.tp2intervals.domain.Platform
import org.freekode.tp2intervals.domain.TrainingType

class PlanWorkoutsRequest(
class ScheduleWorkoutsRequest(
val startDate: LocalDate,
val endDate: LocalDate,
val types: List<TrainingType>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package org.freekode.tp2intervals.app.workout

import java.time.LocalDate

data class PlanWorkoutsResponse(
data class ScheduleWorkoutsResponse(
val planned: Int,
val filteredOut: Int,
val startDate: LocalDate,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package org.freekode.tp2intervals.app.workout

import org.freekode.tp2intervals.app.schedule.ScheduleService
import org.freekode.tp2intervals.domain.Platform
import org.freekode.tp2intervals.domain.plan.PlanRepository
import org.freekode.tp2intervals.domain.workout.Workout
import org.freekode.tp2intervals.domain.workout.WorkoutRepository
import org.springframework.stereotype.Service

@Service
class WorkoutService(
workoutRepositories: List<WorkoutRepository>,
planRepositories: List<PlanRepository>,
private val scheduleService: ScheduleService
) {
private val workoutRepositoryMap = workoutRepositories.associateBy { it.platform() }
private val planRepositoryMap = planRepositories.associateBy { it.platform() }

fun planWorkouts(request: PlanWorkoutsRequest): PlanWorkoutsResponse {
fun copyPlannedWorkouts(request: ScheduleWorkoutsRequest): ScheduleWorkoutsResponse {
val sourceWorkoutRepository = workoutRepositoryMap[request.sourcePlatform]!!
val targetWorkoutRepository = workoutRepositoryMap[request.targetPlatform]!!

Expand All @@ -29,7 +29,7 @@ class WorkoutService(
.filter { !plannedWorkouts.contains(it) }
}

val response = PlanWorkoutsResponse(
val response = ScheduleWorkoutsResponse(
filteredWorkoutsToPlan.size,
allWorkoutsToPlan.size - filteredWorkoutsToPlan.size,
request.startDate,
Expand All @@ -39,15 +39,7 @@ class WorkoutService(
return response
}

fun addScheduledPlanWorkoutsRequest(request: PlanWorkoutsRequest) {
scheduleService.addScheduledRequest(request)
}

fun getScheduledPlanWorkoutsRequest(): PlanWorkoutsRequest? {
return scheduleService.getScheduledRequest(PlanWorkoutsRequest::class.java)
}

fun copyWorkouts(request: CopyWorkoutsRequest): CopyWorkoutsResponse {
fun copyPlannedWorkoutsToLibrary(request: CopyWorkoutsRequest): CopyWorkoutsResponse {
val sourceWorkoutRepository = workoutRepositoryMap[request.sourcePlatform]!!
val targetWorkoutRepository = workoutRepositoryMap[request.targetPlatform]!!
val targetPlanRepository = planRepositoryMap[request.targetPlatform]!!
Expand All @@ -56,9 +48,13 @@ class WorkoutService(
val filteredWorkouts = allWorkouts.filter { request.types.contains(it.type) }

val plan = targetPlanRepository.createPlan(request.name, request.startDate, request.isPlan)
filteredWorkouts.forEach { targetWorkoutRepository.saveWorkout(it, plan) }
filteredWorkouts.forEach { targetWorkoutRepository.saveWorkoutToLibrary(it, plan) }
return CopyWorkoutsResponse(
filteredWorkouts.size, allWorkouts.size - filteredWorkouts.size, request.startDate, request.endDate
)
}

fun findWorkoutsByName(platform: Platform, name: String): List<Workout> {
TODO("not implemented")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import org.freekode.tp2intervals.infrastructure.utils.Date
data class Plan(
val name: String,
val startDate: LocalDate,
val isPlan: Boolean,
val externalData: ExternalData,
) : Serializable {
companion object {
fun fromMonday(name: String, externalData: ExternalData): Plan {
return Plan(name, Date.thisMonday(), externalData)
fun planFromMonday(name: String, externalData: ExternalData): Plan {
return Plan(name, Date.thisMonday(), true, externalData)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ interface PlanRepository {

fun createPlan(name: String, startDate: LocalDate, isPlan: Boolean): Plan

fun getPlans(): List<Plan>
fun getLibraries(): List<Plan>
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.freekode.tp2intervals.domain.workout

import java.io.Serializable
import java.time.Duration
import java.time.LocalDate
import org.freekode.tp2intervals.domain.ExternalData
Expand All @@ -15,7 +16,7 @@ data class Workout(
val load: Int?,
val structure: WorkoutStructure?,
val externalData: ExternalData,
) {
) : Serializable {
companion object {
fun note(date: LocalDate, title: String, description: String?, externalData: ExternalData): Workout {
return Workout(date, TrainingType.NOTE, title, description, null, null, null, externalData)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
package org.freekode.tp2intervals.domain.workout

import java.time.LocalDate
import org.freekode.tp2intervals.domain.Platform
import org.freekode.tp2intervals.domain.plan.Plan
import java.time.LocalDate

interface WorkoutRepository {
fun platform(): Platform

fun getPlannedWorkouts(startDate: LocalDate, endDate: LocalDate): List<Workout>

fun getWorkout(id: String): Workout

fun getWorkouts(plan: Plan): List<Workout>

fun planWorkout(workout: Workout)

fun saveWorkout(workout: Workout, plan: Plan)
fun getWorkoutsFromLibrary(plan: Plan): List<Workout>

fun saveWorkoutToLibrary(workout: Workout, plan: Plan)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.freekode.tp2intervals.domain.workout.structure

interface WorkoutStep {
import java.io.Serializable

interface WorkoutStep : Serializable {
fun isSingleStep(): Boolean
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.freekode.tp2intervals.domain.workout.structure

import java.io.Serializable

data class WorkoutStepTarget(
val start: Int,
val end: Int
)
): Serializable
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.freekode.tp2intervals.domain.workout.structure

import java.io.Serializable

data class WorkoutStructure(
val target: TargetUnit,
val steps: List<WorkoutStep>,
) {
) : Serializable {
init {
if (steps.isEmpty()) throw IllegalStateException("There must be at least one step in workout structure")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.freekode.tp2intervals.infrastructure

class Signature {
companion object {
val description = """
Created by tp2intervals (https://github.com/freekode/tp2intervals)
""".trimIndent()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@ import org.springframework.web.multipart.MultipartFile
)
interface IntervalsApiClient {

@PostMapping("/api/v1/athlete/{athleteId}/folders")
fun createFolder(
@PathVariable("athleteId") athleteId: String,
@RequestBody createFolderRequestDTO: CreateFolderRequestDTO
): FolderDTO

@PostMapping("/api/v1/athlete/{athleteId}/workouts")
fun createWorkout(
@PathVariable("athleteId") athleteId: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.freekode.tp2intervals.infrastructure.platform.intervalsicu.folder

import org.freekode.tp2intervals.infrastructure.platform.intervalsicu.IntervalsApiClientConfig
import org.springframework.cloud.openfeign.FeignClient
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody

@FeignClient(
value = "IntervalsFolderApiClient",
url = "\${intervals.api-url}",
dismiss404 = true,
primary = false,
configuration = [IntervalsApiClientConfig::class]
)
interface IntervalsFolderApiClient {

@PostMapping("/api/v1/athlete/{athleteId}/folders")
fun createFolder(
@PathVariable("athleteId") athleteId: String,
@RequestBody createFolderRequestDTO: CreateFolderRequestDTO
): FolderDTO

@GetMapping("/api/v1/athlete/{athleteId}/folders")
fun getFolders(
@PathVariable("athleteId") athleteId: String,
): List<FolderDTO>
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,49 @@ import org.freekode.tp2intervals.domain.ExternalData
import org.freekode.tp2intervals.domain.Platform
import org.freekode.tp2intervals.domain.plan.Plan
import org.freekode.tp2intervals.domain.plan.PlanRepository
import org.freekode.tp2intervals.infrastructure.platform.intervalsicu.IntervalsApiClient
import org.freekode.tp2intervals.infrastructure.Signature
import org.freekode.tp2intervals.infrastructure.platform.intervalsicu.configuration.IntervalsConfigurationRepository
import org.springframework.cache.annotation.CacheConfig
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Repository


@CacheConfig(cacheNames = ["libraryItemsCache"])
@Repository
class IntervalsFolderRepository(
private val intervalsApiClient: IntervalsApiClient,
private val intervalsFolderApiClient: IntervalsFolderApiClient,
private val intervalsConfigurationRepository: IntervalsConfigurationRepository
) : PlanRepository {
private val planDescription = """
Created by tp2intervals (https://github.com/freekode/tp2intervals)
""".trimIndent()

override fun platform() = Platform.INTERVALS

override fun createPlan(name: String, startDate: LocalDate, isPlan: Boolean): Plan {
val folderType = if (isPlan) "PLAN" else "FOLDER"
val newFolder = createFolder(name, startDate, folderType)
return Plan(newFolder.name, newFolder.startDateLocal!!, ExternalData.empty().withIntervals(newFolder.id))
return toPlan(newFolder)
}

override fun getPlans(): List<Plan> {
TODO("Not yet implemented")
@Cacheable(key = "'INTERVALS'")
override fun getLibraries(): List<Plan> {
return intervalsFolderApiClient.getFolders(intervalsConfigurationRepository.getConfiguration().athleteId)
.map { toPlan(it) }
}

private fun createFolder(name: String, startDate: LocalDate?, type: String): FolderDTO {
val createRequest = CreateFolderRequestDTO(
0, name, planDescription, 0, startDate?.toString(), -1, -1, type
0, name, Signature.description, 0, startDate?.toString(), -1, -1, type
)
return intervalsApiClient.createFolder(
return intervalsFolderApiClient.createFolder(
intervalsConfigurationRepository.getConfiguration().athleteId,
createRequest
)
}

private fun toPlan(folderDTO: FolderDTO): Plan {
return if (folderDTO.type == "PLAN") {
Plan(folderDTO.name, folderDTO.startDateLocal!!, true, ExternalData.empty().withIntervals(folderDTO.id))
} else {
Plan.planFromMonday(folderDTO.name, ExternalData.empty().withIntervals(folderDTO.id))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class IntervalsWorkoutRepository(
intervalsApiClient.createEvent(intervalsConfigurationRepository.getConfiguration().athleteId, request)
}

override fun saveWorkout(workout: Workout, plan: Plan) {
override fun saveWorkoutToLibrary(workout: Workout, plan: Plan) {
val workoutString = getWorkoutString(workout)
val description = getDescription(workout, workoutString)

Expand Down Expand Up @@ -69,11 +69,7 @@ class IntervalsWorkoutRepository(
.mapNotNull { toWorkout(it) }
}

override fun getWorkout(id: String): Workout {
TODO("Not yet implemented")
}

override fun getWorkouts(plan: Plan): List<Workout> {
override fun getWorkoutsFromLibrary(plan: Plan): List<Workout> {
TODO("Not yet implemented")
}

Expand Down
Loading

0 comments on commit 099b5fb

Please sign in to comment.