Autocomplete feedback loop: implicit rejection + weekly rating
A) Implicit: HomeViewModel tracks auto-assigned slot IDs after each autocomplete run. When the user manually replaces one of those dishes, the rejected dish ID is recorded in FeedbackStore (UserDefaults). AutocompleteEngine applies a 25% penalty per rejection (floor 0.30). B) Explicit: WeekPlan gains userRating (0/1/-1). Past weeks with dishes show a compact 👍/👎 row (Premium only). Liked weeks boost their dishes (+0.20 each, max +0.50); disliked weeks penalise them (-0.25 each, max -0.50). Signal is intentionally modest so the period cycle score remains dominant. Also adds Stats + week-rating localization strings to all 6 languages (were missing from the previous commit). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ final class HomeViewModel: ObservableObject {
|
||||
}
|
||||
|
||||
@Published var currentWeekStart: Date
|
||||
private var autoAssignedSlotIds: Set<UUID> = []
|
||||
@Published var isAutoCompleting: Bool = false
|
||||
@Published var showConfetti: Bool = false
|
||||
@Published var showToast: Bool = false
|
||||
@@ -80,6 +81,11 @@ final class HomeViewModel: ObservableObject {
|
||||
}
|
||||
|
||||
func assignDish(_ dish: Dish, to slot: MealSlot, plan: WeekPlan, settings: AppSettings, isOverride: Bool = false) {
|
||||
if autoAssignedSlotIds.contains(slot.id),
|
||||
let previous = slot.dishId, previous != dish.id {
|
||||
FeedbackStore.recordRejection(for: previous)
|
||||
autoAssignedSlotIds.remove(slot.id)
|
||||
}
|
||||
captureUndoSnapshot(plan: plan)
|
||||
|
||||
if let oldEventId = slot.calendarEventId {
|
||||
@@ -128,8 +134,10 @@ final class HomeViewModel: ObservableObject {
|
||||
currentPlan: plan,
|
||||
allDishes: dishes,
|
||||
allTags: tags,
|
||||
recentPlans: Array(recentPlans)
|
||||
recentPlans: Array(recentPlans),
|
||||
rejectionCounts: FeedbackStore.rejectionCounts()
|
||||
)
|
||||
autoAssignedSlotIds = Set(result.filledSlots.map(\.slotId))
|
||||
|
||||
plan.updatedAt = Date()
|
||||
applyCalendarSyncPolicy(plan: plan, settings: settings, shouldNotify: false)
|
||||
@@ -157,7 +165,14 @@ final class HomeViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func rateWeek(plan: WeekPlan, rating: Int) {
|
||||
plan.userRating = rating
|
||||
plan.updatedAt = Date()
|
||||
HapticManager.shared.impact(style: .light)
|
||||
}
|
||||
|
||||
func resetWeek(plan: WeekPlan, settings: AppSettings) {
|
||||
autoAssignedSlotIds = []
|
||||
captureUndoSnapshot(plan: plan)
|
||||
|
||||
for slot in plan.slots {
|
||||
|
||||
Reference in New Issue
Block a user