All four steps are complete. Here's the summary: ## What was done 1. **Lambda introduced** (manual edit): the `scorer.updateSelection()` + `scorer.lookupWeather(...)` code became a `LongFunction dayOffsetToWeather` lambda defined at the top of the method; the loop now calls `dayOffsetToWeather.apply(daysForward)`. 2. **Extracted** the weather-collection loop with `java-refactor extract` (the tool generated `collectExpectedWeather(interestingDates, dayOffsetToWeather, expectedWeather)`), then a minimal manual cleanup gave it the suggested shape `private List collectExpectedWeather(LongFunction dayOffsetToWeather)` returning the list. 3. **Signature changed** (manual edit — neither `change-method-signature` nor `introduce-param` supports removing the `quarter` parameter): now `public Map longRangeForecast(LongFunction dayOffsetToWeather)` plus a public no-arg overload delegating with a lambda wrapping the `scorer` field. The `quarter` branch was dropped (it was inert anyway — its `put(flavour, 5)` was immediately overwritten by `put(flavour, 0)`), and the test call site updated to `longRangeForecast()`. 4. `mvn -q test` was run after every change: code compiles throughout; the 2 remaining failures (`LongRangeForecastsTest`, `DailyForecastsTest`) are the expected pre-existing ones caused by the `Scorer` state dependency. ## Final diff — `src/main/java/codingdojo/LongRangeForecasts.java` ```diff @@ -3,36 +3,26 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.*; +import java.util.function.LongFunction; public class LongRangeForecasts { private final Scorer scorer = new Scorer(); - public Map longRangeForecast(String quarter) { + public Map longRangeForecast() { + return longRangeForecast(daysForward -> { + scorer.updateSelection(); + return scorer.lookupWeather(daysForward); + }); + } + + public Map longRangeForecast(LongFunction dayOffsetToWeather) { var result = new HashMap(); - if (Objects.equals(quarter, "Q1") || Objects.equals(quarter, "Q4")) { - for (IceCream flavour : IceCream.values()) { - result.put(flavour, 5); - } - } for (IceCream flavour : IceCream.values()) { result.put(flavour, 0); } - List interestingDates = List.of( - Instant.parse("2023-05-01T14:00:00.000-07:00"), - Instant.parse("2023-05-18T14:00:00.000-07:00"), - Instant.parse("2023-06-05T14:00:00.000-07:00"), - Instant.parse("2023-06-23T14:00:00.000-07:00") - ); - List expectedWeather = new ArrayList<>(); - for (Instant interestingDate : interestingDates) { - scorer.updateSelection(); - var forecastDate = Instant.parse("2023-04-26T14:00:00.000-07:00"); - long daysForward = ChronoUnit.DAYS.between(forecastDate, interestingDate); - Boolean lookupWeather = scorer.lookupWeather(daysForward); - expectedWeather.add(lookupWeather); - } + var expectedWeather = collectExpectedWeather(dayOffsetToWeather); for (IceCream flavour : result.keySet()) { result.put(flavour, result.get(flavour) + 10); @@ -46,4 +36,21 @@ } return result; } + + private List collectExpectedWeather(LongFunction dayOffsetToWeather) { + List interestingDates = List.of( + Instant.parse("2023-05-01T14:00:00.000-07:00"), + Instant.parse("2023-05-18T14:00:00.000-07:00"), + Instant.parse("2023-06-05T14:00:00.000-07:00"), + Instant.parse("2023-06-23T14:00:00.000-07:00") + ); + List expectedWeather = new ArrayList<>(); + for (Instant interestingDate : interestingDates) { + var forecastDate = Instant.parse("2023-04-26T14:00:00.000-07:00"); + long daysForward = ChronoUnit.DAYS.between(forecastDate, interestingDate); + Boolean lookupWeather = dayOffsetToWeather.apply(daysForward); + expectedWeather.add(lookupWeather); + } + return expectedWeather; + } } ``` Supporting change in `src/test/java/codingdojo/LongRangeForecastsTest.java`: ```diff - var quarter = "Q3"; - var actual = new LongRangeForecasts().longRangeForecast(quarter); + var actual = new LongRangeForecasts().longRangeForecast(); ``` Stopping here as instructed.