The previous lesson calculated remaining time but did not handle a zero target or study time beyond the target. Useful programs need clear rules for these situations. This lesson extracts a status calculation into a function, selects results with conditions, and adds multiple study sessions with a loop. The complete example still runs independently in Kotlin Playground, without an Android project or additional libraries.
Write the rules before writing code. The target must be positive, and studied minutes cannot be negative. With zero studied minutes, the status is Not started. With positive study time below the target, it is In progress. At or beyond the target, it is Complete. These statements give you something concrete to check instead of deciding afterward that whatever output appears must be acceptable.
Give a function one clear responsibility
A function receives values through parameters and returns a result. Rather than putting every decision in main, learningStatus concentrates the status rules in one place. Callers provide studied minutes and a target, and the function chooses the appropriate message. Reusing it for several plans avoids copying a condition block and accidentally changing only one copy when the rule needs updating.
Name parameters so their meaning and unit are clear. Int says that this function expects whole minutes; String says that its result is a text message. We are not adding keyboard input or file storage yet. Keeping the calculation independent makes it easier to check with known values before connecting it to a form, a database, or another source of data.
Run the complete example
fun learningStatus(studiedMinutes: Int, targetMinutes: Int): String {
if (targetMinutes <= 0 || studiedMinutes < 0) {
return "Invalid input"
}
return when {
studiedMinutes == 0 -> "Not started"
studiedMinutes < targetMinutes -> "In progress"
else -> "Complete"
}
}
fun main() {
val sessions = listOf(15, 20, 10)
var totalMinutes = 0
for (minutes in sessions) {
totalMinutes += minutes
}
println("Total study time: $totalMinutes minutes")
println(learningStatus(totalMinutes, 60))
check(learningStatus(0, 60) == "Not started")
check(learningStatus(45, 60) == "In progress")
check(learningStatus(60, 60) == "Complete")
check(learningStatus(75, 60) == "Complete")
check(learningStatus(5, 0) == "Invalid input")
check(learningStatus(-1, 60) == "Invalid input")
println("All status checks passed")
}
The output reports 45 minutes, then In progress, then the confirmation that all status checks passed. check throws an error if its condition is false. These checks catch behavior changes when you edit the function. For this exercise they sit directly in main; in a larger project, comparable cases can be organized into a separate test suite that runs without the normal program flow.
Read conditions in order
The || operator means either invalid condition is enough: a nonpositive target or negative studied time. return inside the if block ends the function immediately with Invalid input. This means the later branches can be read assuming the values passed validation. The == operator compares values, whereas = appears in assignment. Keeping those roles separate prevents a common misunderstanding when starting with conditions.
This when expression has no subject in parentheses. It evaluates branch conditions in order and uses the first matching branch. else covers the remaining valid cases. If study time is neither zero nor below the target, it has reached or exceeded the target. Complete therefore describes the final branch. Moving branches around without considering overlap can change behavior even if each individual condition looks reasonable.
Use if to produce a value
An if expression can calculate a value as well as control execution. For a fixed sixty-minute target, a remaining-time expression can choose zero when totalMinutes is at least sixty and otherwise choose sixty minus totalMinutes. If you need that rule in several places, put it into a function with a target parameter rather than repeating the fixed target throughout the program.
Do not confuse making output look reasonable with validating input. Clamping a remainder to zero does not explain what should happen when studied time is negative. learningStatus treats that case explicitly. Later models can represent richer outcomes when a text message is no longer enough. For now, a separate invalid-input branch keeps the assumption visible and lets your checks verify it.
Follow a loop through the sessions
listOf creates three session durations: fifteen, twenty, and ten minutes. The for loop takes each duration in turn and binds it to minutes for that iteration. totalMinutes starts at zero and increases after each step. Write down the intermediate totals of fifteen, thirty-five, and forty-five to follow the process. Tracking intermediate values is useful when a final total does not match your prediction.
The example assumes each session duration is valid. If sessions come from user input, validate each one before adding it. A negative session could be offset by a positive session, leaving a positive total that passes the final status validation. Checking the total does not replace checking every item. State this assumption so callers do not mistake one function's responsibility for protection of the entire data pipeline.
Explore boundary cases
Replace the sessions with listOf<Int>() to create an empty list with an explicit element type. The loop performs no iterations, leaving the total at zero and the status at Not started for a sixty-minute target. Next, try one session of sixty minutes and one of sixty-one in separate runs. Both should produce Complete according to the rules, even though the amount beyond the target differs.
Set the target to zero and verify that status calculation returns Invalid input. Do not calculate a percentage by dividing by that target afterward. When a value violates a required condition, decide how to respond before performing dependent arithmetic. The early if branch illustrates this principle in a small function that you can inspect completely.
Complete the function exercise
Write remainingMinutes with studied and target parameters. Require valid input, then return zero at or above the target and the difference below it. Kotlin's require function throws IllegalArgumentException when its condition fails. Check input pairs of zero and sixty, forty-five and sixty, sixty and sixty, and seventy-five and sixty. Their expected results are sixty, fifteen, zero, and zero respectively.
You have completed this lesson when you can explain branch order, trace the loop's total, and distinguish item validation from total validation. The next lesson groups a task's title, duration, and completion into a data class and transforms lists with lambdas. Review control flow and function declarations if you want more examples before moving on.
