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:
alexandrev-tibco
2026-05-27 18:09:15 +02:00
parent e13771fa06
commit 84b74f9ea4
12 changed files with 195 additions and 6 deletions
+4
View File
@@ -86,6 +86,7 @@
FB0011111111111111111108 /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = FB001111111111111111110B /* FirebaseCrashlytics */; };
FB0011111111111111111109 /* CrashlyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB001111111111111111110A /* CrashlyticsService.swift */; };
443CC3997A9A4818B51066FB /* StatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8AD94FC874467D863D464C /* StatsView.swift */; };
B4D6F8012C3E5F7A91B3D5F7 /* FeedbackStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3C5F7891B2D4E6F80A2C4E6 /* FeedbackStore.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -200,6 +201,7 @@
FE73D5B7AF8B5E2D63105977 /* Font+MealMood.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Font+MealMood.swift"; sourceTree = "<group>"; };
FF2DE77AD57DB6DAB188CD9E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
1E8AD94FC874467D863D464C /* StatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsView.swift; sourceTree = "<group>"; };
A3C5F7891B2D4E6F80A2C4E6 /* FeedbackStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackStore.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -487,6 +489,7 @@
103374A7D91B4F884278DA72 /* StoreManager.swift */,
A6FC2153490D53B80DBDC034 /* WidgetDataStore.swift */,
928E6D4F6D78AD1840245FB4 /* PremiumSyncService.swift */,
A3C5F7891B2D4E6F80A2C4E6 /* FeedbackStore.swift */,
);
path = Services;
sourceTree = "<group>";
@@ -697,6 +700,7 @@
25B3C328E088A403CABAF20A /* PremiumSyncService.swift in Sources */,
FB0011111111111111111109 /* CrashlyticsService.swift in Sources */,
443CC3997A9A4818B51066FB /* StatsView.swift in Sources */,
B4D6F8012C3E5F7A91B3D5F7 /* FeedbackStore.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};