Skip to content

Commit

Permalink
Add more project steps
Browse files Browse the repository at this point in the history
  • Loading branch information
nbirillo committed Sep 28, 2024
1 parent 462428e commit 7a097a7
Show file tree
Hide file tree
Showing 293 changed files with 4,800 additions and 1,659 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.jetbrains.kotlin.course.culinary.game

import org.jetbrains.kotlin.course.culinary.converters.toItemType
import org.jetbrains.kotlin.course.culinary.game.CookingService.Companion.NUM_VEGETABLES_FOR_SALAD
import org.jetbrains.kotlin.course.culinary.game.recipes.NUMBER_OF_TOMATOES
import org.jetbrains.kotlin.course.culinary.game.recipes.NUM_VEGETABLES_FOR_SALAD
import org.jetbrains.kotlin.course.culinary.implementation.storage.FridgeImpl
import org.jetbrains.kotlin.course.culinary.models.ItemType
import org.jetbrains.kotlin.course.culinary.models.Task
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.jetbrains.kotlin.course.culinary.game

import org.jetbrains.kotlin.course.culinary.game.recipes.*
import org.jetbrains.kotlin.course.culinary.models.food.CutVegetable
import org.jetbrains.kotlin.course.culinary.models.food.Vegetable
import org.springframework.stereotype.Service

@Service
class CookingService {
fun cookTomatoSoup() {
val tomatoes = getTomatoesForSoup()
prepareTomatoes(tomatoes)
pot.simmer()
}

fun cookWithSpices() {
val spices = generateSpices()
addSpices(spices)
pot.simmer()
}

fun cookSaladAsList() {
mixVegetablesForSalad(getFreshVegetables().cut())
}

fun cookSaladAsSequence() {
mixVegetablesForSalad(getFreshVegetables().asSequence().cut())
}

private fun Sequence<Vegetable>.cut(): List<CutVegetable> = map { kitchen.put(it) }
.map { kitchen.cut(it) }
.take(NUM_VEGETABLES_FOR_SALAD)
.map { kitchen.take(it) }
.toList()

fun cookSmoothie(){
getFruitsForSmoothie().cookSmoothie()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.jetbrains.kotlin.course.culinary.game.recipes

import org.jetbrains.kotlin.course.culinary.models.food.CutVegetable
import org.jetbrains.kotlin.course.culinary.models.food.Vegetable

const val NUM_VEGETABLES_FOR_SALAD = 5

fun getFreshVegetables(): List<Vegetable> = TODO("Not implemented yet")

fun List<Vegetable>.cut(): List<CutVegetable> = TODO("Not implemented yet")

fun mixVegetablesForSalad(cutVegetables: List<CutVegetable>) {
TODO("Not implemented yet")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.jetbrains.kotlin.course.culinary.game.recipes

import org.jetbrains.kotlin.course.culinary.models.food.Fruit

fun getFruitsForSmoothie(): List<Fruit> = TODO("Not implemented yet")

fun List<Fruit>.cookSmoothie() {
TODO("Not implemented yet")
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,20 @@ import org.jetbrains.kotlin.course.culinary.models.food.Vegetable
import org.jetbrains.kotlin.course.culinary.models.food.VegetableType
import kotlin.random.Random

internal const val NUMBER_OF_TOMATOES = 3
const val NUMBER_OF_TOMATOES = 3

// TODO: add tests
// task#1
fun getTomatoesForSoup(): List<Vegetable> =
List(NUMBER_OF_TOMATOES) { fridge.getVegetable(what = VegetableType.Tomato) }

// TODO: add tests
// task#1
fun prepareTomatoes(tomatoes: List<Vegetable>) {
tomatoes
.onEach { kitchen.put(it) }
.map { kitchen.cut(it) }
.forEach { pot.put(kitchen.take(it)) }
}

fun cookSoup() {
pot.simmer()
}

// task#2
fun generateSpices(): Sequence<SpiceType> = generateSequence { SpiceType.entries.random() }

// task#2
fun addSpices(spices: Sequence<SpiceType>) {
val howMuchToAdd = Random.nextInt(1, 4)
spices
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ data object PotImpl : Pot {
val filling: MutableList<Ingredient> = mutableListOf()
var simmering: Boolean = false

override fun doesTastePerfect(): Boolean = filling.filter{ it is Spice }
.groupingBy{ it }
.eachCount()
.filter{ (_, n) -> n > 2 }
.isEmpty()

override fun <T: Ingredient> put(ingredient: T) {
filling.add(ingredient)
actions.add(buildAction(ActionType.PUT_IN_POT, ingredient))
Expand All @@ -21,13 +27,6 @@ data object PotImpl : Pot {
actions.add(buildAction(ActionType.PUT_IN_POT, vegetable))
}

// task#2
override fun doesTastePerfect(): Boolean = filling.filter{ it is Spice }
.groupingBy{ it }
.eachCount()
.filter{ (_, n) -> n > 2 }
.isEmpty()

override fun simmer() {
check(!simmering) { "You are already simmering" }
simmering = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,21 @@ import org.jetbrains.kotlin.course.culinary.models.storage.Fridge
import kotlin.random.Random

data object FridgeImpl : Fridge {
private const val RANDOM_VEGETABLES_NUMBER = 7
private const val RANDOM_FRESH_VEGETABLES_NUMBER = 3
const val RANDOM_VEGETABLES_NUMBER = 7
const val RANDOM_FRESH_VEGETABLES_NUMBER = 3

val vegetables: MutableList<Vegetable> = mutableListOf()

// TODO: add tests
private fun generateRandomVegetables() = buildList {
addAll(List(RANDOM_VEGETABLES_NUMBER) { Vegetable(VegetableType.entries.random(), Random.nextBoolean()) })
addAll(List(RANDOM_FRESH_VEGETABLES_NUMBER) { Vegetable(VegetableType.entries.random(), true) })
}

// TODO: add tests
// Task#0, student
fun refill() {
vegetables.clear()
vegetables.addAll(generateRandomVegetables())
}

// TODO: add tests
// task#1, student
override fun getVegetable(what: VegetableType): Vegetable {
val vegetable = checkNotNull(vegetables.find { it.type == what && it.isFresh }) { "Fresh vegetable $what not found." }
vegetables.remove(vegetable)
Expand Down
70 changes: 70 additions & 0 deletions culinaryServer/culinaryServerAddSpices/task-info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
type: edu
custom_name: Master Chef - Add Spices
files:
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/MasterChefApplication.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/game/GameResource.kt
visible: false
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/game/GameService.kt
visible: false
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/food/IngredientType.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/food/Ingredient.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/storage/Fridge.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/storage/Shelf.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/cooking/Pot.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/storage/Basket.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/cooking/SaladBowl.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/cooking/Blender.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/implementation/storage/FridgeImpl.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/implementation/storage/ShelfImpl.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/implementation/cooking/PotImpl.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/implementation/cooking/SaladBowlImpl.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/Resettable.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/implementation/cooking/BlenderImpl.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/Kitchen.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/implementation/KitchenImpl.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/game/GameEnviroment.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/game/GameActions.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/game/recipes/TomatoSoup.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/action/Action.kt
visible: false
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/action/ActionType.kt
visible: false
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/ItemType.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/converters/ItemTypeConverter.kt
visible: false
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/models/Task.kt
visible: false
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/game/recipes/Salad.kt
visible: true
- name: src/main/kotlin/org/jetbrains/kotlin/course/culinary/game/recipes/Smoothie.kt
visible: true
- name: test/FridgeImplTestClass.kt
visible: false
propagatable: false
- name: test/Tests.kt
visible: false
propagatable: false
- name: test/TomatoSoupFunctions.kt
visible: false
propagatable: false
1 change: 1 addition & 0 deletions culinaryServer/culinaryServerAddSpices/task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: coding task, generateSpices and addSpices
27 changes: 27 additions & 0 deletions culinaryServer/culinaryServerAddSpices/test/FridgeImplTestClass.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import org.jetbrains.academy.test.system.core.models.TestKotlinType
import org.jetbrains.academy.test.system.core.models.Visibility
import org.jetbrains.academy.test.system.core.models.classes.ClassType
import org.jetbrains.academy.test.system.core.models.classes.TestClass
import org.jetbrains.academy.test.system.core.models.method.TestMethod

internal val generateRandomVegetablesMethod = TestMethod(
"generateRandomVegetables",
TestKotlinType("List", params = listOf("org.jetbrains.kotlin.course.culinary.ingredient.Vegetable")),
visibility = Visibility.PRIVATE,
)

internal val refillMethod = TestMethod(
"refill",
TestKotlinType("Unit"),
returnTypeJava = "void",
)

internal val fridgeImplTestClass = TestClass(
"FridgeImpl",
"org.jetbrains.kotlin.course.culinary.implementation.storage",
classType = ClassType.OBJECT,
customMethods = listOf(
generateRandomVegetablesMethod,
refillMethod
),
)
115 changes: 115 additions & 0 deletions culinaryServer/culinaryServerAddSpices/test/Tests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import org.jetbrains.academy.test.system.core.findMethod
import org.jetbrains.academy.test.system.core.invokeWithArgs
import org.jetbrains.academy.test.system.core.invokeWithoutArgs
import org.jetbrains.academy.test.system.core.models.classes.ConstructorGetter
import org.jetbrains.kotlin.course.culinary.game.actions
import org.jetbrains.kotlin.course.culinary.game.clearActions
import org.jetbrains.kotlin.course.culinary.game.recipes.NUMBER_OF_TOMATOES
import org.jetbrains.kotlin.course.culinary.implementation.storage.FridgeImpl
import org.jetbrains.kotlin.course.culinary.implementation.storage.FridgeImpl.RANDOM_FRESH_VEGETABLES_NUMBER
import org.jetbrains.kotlin.course.culinary.implementation.storage.FridgeImpl.RANDOM_VEGETABLES_NUMBER
import org.jetbrains.kotlin.course.culinary.models.ItemType
import org.jetbrains.kotlin.course.culinary.models.action.Action
import org.jetbrains.kotlin.course.culinary.models.action.ActionType
import org.jetbrains.kotlin.course.culinary.models.food.Vegetable
import org.jetbrains.kotlin.course.culinary.models.food.VegetableType
import org.junit.jupiter.api.Test
import java.lang.reflect.InvocationTargetException

class Test {
// TODO: add tests for the current task

@Test
fun getTomatoesForSoupMethodTest() {
val clazz = tomatoSoupKtTestClass.checkBaseDefinition()
val method = clazz.declaredMethods.findMethod(getTomatoesForSoupMethod)
FridgeImpl.vegetables.addAll(generateTomatoesForSoup())

val vegetables: List<Vegetable> = try {
method.invokeWithoutArgs(clazz = clazz) as List<Vegetable>
} catch(e: InvocationTargetException) {
assert(false) { "Can not invoke method ${method.name}. Please, add an implementation!" }
emptyList()
}

assert(vegetables.all{ it.type == VegetableType.Tomato && it.isFresh }) { "Method ${method.name} should generate only fresh tomatoes" }
assert(vegetables.size == NUMBER_OF_TOMATOES) { "Method ${method.name} should generate ${NUMBER_OF_TOMATOES} tomatoes, currently it generates ${vegetables.size} tomatoes" }
}

@Test
fun prepareTomatoesMethodTest() {
clearActions()
val clazz = tomatoSoupKtTestClass.checkBaseDefinition()
val method = clazz.declaredMethods.findMethod(prepareTomatoesMethod)

try {
method.invoke(clazz, generateTomatoesForSoup())
} catch(e: InvocationTargetException) {
assert(false) { "Can not invoke method ${method.name}. Please, add an implementation!" }
}

val expectedActions = buildList {
addAll(List(NUMBER_OF_TOMATOES) { Action(ActionType.SHOW_ON_COUNTER, ItemType.FRESH_TOMATO) })
repeat(NUMBER_OF_TOMATOES) {
addAll(listOf(
Action(ActionType.CUT_ON_COUNTER, ItemType.FRESH_TOMATO),
Action(ActionType.SHOW_ON_COUNTER, ItemType.CUT_TOMATO)
))
}
repeat(NUMBER_OF_TOMATOES) {
addAll(listOf(
Action(ActionType.REMOVE_FROM_COUNTER, ItemType.CUT_TOMATO),
Action(ActionType.PUT_IN_POT, ItemType.CUT_TOMATO)
))
}
}

assert(actions == expectedActions) { "The ${method.name} should cook a tomato soup in the following algorithm: put each tomato into the kitchen, then cut each tomato, then take each cut tomato and put each tomato into the pot." }
}

private fun generateTomatoesForSoup() = List(NUMBER_OF_TOMATOES) { Vegetable(VegetableType.Tomato, true) }

@Test
fun generateRandomVegetablesMethodTest() {
val vegetables = generateRandomVegetables()
val expectedNumOfVegetables = RANDOM_VEGETABLES_NUMBER + RANDOM_FRESH_VEGETABLES_NUMBER
assert(vegetables.size == expectedNumOfVegetables) { "You need to generate $expectedNumOfVegetables vegetables" }
assert(vegetables.toSet().size > 1) { "You need to generate different random vegetables!" }
assert(vegetables.filter{ it.isFresh }.size >= RANDOM_FRESH_VEGETABLES_NUMBER) { "You need to generate at least $RANDOM_FRESH_VEGETABLES_NUMBER fresh vegetables" }
}

private fun generateRandomVegetables(): List<Vegetable> {
val clazz = fridgeImplTestClass.checkBaseDefinition()
val method = clazz.declaredMethods.findMethod(generateRandomVegetablesMethod)
val instance = clazz.fields.find { it.name == "INSTANCE" }?.get(null)

return try {
fridgeImplTestClass.invokeMethodWithoutArgs(clazz, instance, method, true) as List<Vegetable>
} catch(e: InvocationTargetException) {
assert(false) { "Can not invoke method ${method.name}. Please, add an implementation!" }
emptyList()
}
}

@Test
fun refillMethodTest() {
val clazz = fridgeImplTestClass.checkBaseDefinition()
val method = clazz.declaredMethods.findMethod(refillMethod)
val instance = clazz.fields.find { it.name == "INSTANCE" }?.get(null)

val vegetablesNumInitial = FridgeImpl.vegetables.size
FridgeImpl.vegetables.addAll(generateRandomVegetables())
val vegetablesNumBeforeRefill = FridgeImpl.vegetables.size
assert(vegetablesNumBeforeRefill - vegetablesNumInitial > 0) { "Method ${generateRandomVegetablesMethod.name} should generate random vegetables!" }

try {
method.invoke(instance)
} catch(e: InvocationTargetException) {
assert(false) { "Can not invoke method ${method.name}. Please, add an implementation!" }
}

val vegetablesNumAfterRefill = FridgeImpl.vegetables.size
val expectedNumOfVegetables = RANDOM_VEGETABLES_NUMBER + RANDOM_FRESH_VEGETABLES_NUMBER
assert(vegetablesNumAfterRefill == expectedNumOfVegetables) { "Method ${method.name} should add $expectedNumOfVegetables vegetables into the fridge!" }
}
}
Loading

0 comments on commit 7a097a7

Please sign in to comment.