diff --git a/AI/CHANGELOG.md b/AI/CHANGELOG.md index 9dcfd56..f63936f 100644 --- a/AI/CHANGELOG.md +++ b/AI/CHANGELOG.md @@ -50,6 +50,13 @@ - **Impact:** Lesson copy stays on the side panels; timing feedback looks like the level. - **Refs:** `TutorialController.cs`, `TreeRhythmController.cs`, `Assets/Scenes/Tutorial.unity` +### Changed — Results QR link carries grade and score +- **Scope:** component:ResultScreen · integration +- **What:** The share link now encodes four params (`?start=…&placed=…&grade=…&score=…`). `TreeRunTracker.BuildViewerUrl` takes the final `Grade` and score, `TreeResultQrDisplay.PrepareResultQrCode` takes the run's `RhythmScoreTracker`, and both new query keys are editable on `TreeShareConfig`. Default viewer path moves from `/view` to `/results`. +- **Why:** The results web page needs the letter grade and numeric score from the link itself, not only the BST sequences. +- **Impact:** `PrepareResultQrCode` and `BuildViewerUrl` gained parameters; the result screen passes the score tracker it already displays. A missing tracker logs an error and shows the QR fallback instead of an incomplete link. Set `_viewerBaseUrl` per environment on the config asset. +- **Refs:** `TreeShareConfig.cs`, `TreeRunTracker.cs`, `TreeResultQrDisplay.cs`, `ResultScreenController.cs`, `TreeShareConfig.asset` + ### Fixed — Player-side synthwave reacts to the song again in VS Bot / 2P - **Scope:** component:PlayerVsBot - **What:** `TwoPlayerGameCoordinator` now pulses P1's synthwave floor from P1 `OnBeat` (P2 already had this) and retargets the shared `AudioFFTAnalyzer` to P1's playing `AudioSource`. P2 `PlaySync` never starts a clip, so the analyzer had been listening to a silent source — hills stayed flat on the human side while the bot side still kicked from its beat wire. diff --git a/Assets/Integration/TreeResultQrDisplay.cs b/Assets/Integration/TreeResultQrDisplay.cs index 8902ee6..5218301 100644 --- a/Assets/Integration/TreeResultQrDisplay.cs +++ b/Assets/Integration/TreeResultQrDisplay.cs @@ -59,8 +59,12 @@ public void SetTracker(TreeRunTracker tracker) * assigns it to the results-screen RawImage. Safe to call once per run; * subsequent calls for the same run are no-ops until . * + * + * Same tracker the result screen displays; supplies the grade and total + * score encoded in the link. + * */ - public void PrepareResultQrCode() + public void PrepareResultQrCode(RhythmScoreTracker score) { if (_preparedForCurrentRun) return; @@ -72,6 +76,15 @@ public void PrepareResultQrCode() return; } + if (score == null) + { + Debug.LogError("[TreeResultQrDisplay] Missing RhythmScoreTracker — cannot encode grade and score."); + _tracker.FinishLevel(); + ShowFallback(); + _preparedForCurrentRun = true; + return; + } + if (_qrRawImage == null) { Debug.LogError("[TreeResultQrDisplay] Missing QR RawImage reference."); @@ -81,7 +94,7 @@ public void PrepareResultQrCode() } _tracker.FinishLevel(); - _lastUrl = _tracker.BuildViewerUrl(); + _lastUrl = _tracker.BuildViewerUrl(score.CurrentGrade, score.TotalScore); if (string.IsNullOrEmpty(_lastUrl)) { Debug.LogError("[TreeResultQrDisplay] Viewer URL was empty (check TreeShareConfig)."); diff --git a/Assets/Integration/TreeRunTracker.cs b/Assets/Integration/TreeRunTracker.cs index 49e04f5..c0f73ac 100644 --- a/Assets/Integration/TreeRunTracker.cs +++ b/Assets/Integration/TreeRunTracker.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using UnityEngine; /** @@ -7,7 +8,8 @@ * * Holds the starting tree's original insertion order plus every value the * player successfully places, in placement order. Used by - * to build a seemytree viewer URL. + * to build a results viewer URL of the form + * ?start=…&placed=…&grade=…&score=…. * * Attach beside on each GameController. * Does not use DontDestroyOnLoad — lives for the GameScene level only. @@ -123,12 +125,14 @@ public void ResetTracking() } /** - * Builds the seemytree viewer URL for the current run. + * Builds the results viewer URL for the current run. * Empty placement lists are valid and encode as placed=. * Base URL and query names come from . * + * Final letter grade shown on the result screen. + * Final score from . */ - public string BuildViewerUrl() + public string BuildViewerUrl(Grade grade, long score) { if (_shareConfig == null) { @@ -141,12 +145,17 @@ public string BuildViewerUrl() string startEncoded = Uri.EscapeDataString(startJoined); string placedEncoded = Uri.EscapeDataString(placedJoined); + string gradeEncoded = Uri.EscapeDataString(grade.ToString()); + string scoreEncoded = Uri.EscapeDataString(score.ToString(CultureInfo.InvariantCulture)); string baseUrl = _shareConfig.ViewerBaseUrl; string startKey = _shareConfig.StartParamName; string placedKey = _shareConfig.PlacedParamName; + string gradeKey = _shareConfig.GradeParamName; + string scoreKey = _shareConfig.ScoreParamName; - return $"{baseUrl}?{startKey}={startEncoded}&{placedKey}={placedEncoded}"; + return $"{baseUrl}?{startKey}={startEncoded}&{placedKey}={placedEncoded}" + + $"&{gradeKey}={gradeEncoded}&{scoreKey}={scoreEncoded}"; } #endregion diff --git a/Assets/Integration/TreeShareConfig.cs b/Assets/Integration/TreeShareConfig.cs index 3c31a9b..f00e03e 100644 --- a/Assets/Integration/TreeShareConfig.cs +++ b/Assets/Integration/TreeShareConfig.cs @@ -8,9 +8,12 @@ [CreateAssetMenu(menuName = "Treeformance/TreeShareConfig", fileName = "TreeShareConfig")] public class TreeShareConfig : ScriptableObject { + /** Used when the asset leaves _viewerBaseUrl blank. */ + private const string DefaultViewerBaseUrl = "https://seemytree.netlify.app/results"; + [Header("Viewer")] - [Tooltip("Base URL for the tree viewer (no query string). Example: https://seemytree.netlify.app/view")] - [SerializeField] private string _viewerBaseUrl = "https://seemytree.netlify.app/view"; + [Tooltip("Base URL for the results viewer (no query string). Example: https://seemytree.netlify.app/results")] + [SerializeField] private string _viewerBaseUrl = DefaultViewerBaseUrl; [Header("Query Parameter Names")] [Tooltip("Query key for the starting BST insertion order.")] @@ -19,10 +22,16 @@ public class TreeShareConfig : ScriptableObject [Tooltip("Query key for successful player placements in order.")] [SerializeField] private string _placedParamName = "placed"; - /** Host + path used before ?start=…&placed=…. */ + [Tooltip("Query key for the final letter grade (SS, S, A, B, C, D, F).")] + [SerializeField] private string _gradeParamName = "grade"; + + [Tooltip("Query key for the final numeric score.")] + [SerializeField] private string _scoreParamName = "score"; + + /** Host + path used before ?start=…&placed=…&grade=…&score=…. */ public string ViewerBaseUrl => string.IsNullOrWhiteSpace(_viewerBaseUrl) - ? "https://seemytree.netlify.app/view" + ? DefaultViewerBaseUrl : _viewerBaseUrl.TrimEnd('/'); /** Query parameter name for the starting insertion sequence. */ @@ -32,4 +41,12 @@ public class TreeShareConfig : ScriptableObject /** Query parameter name for successful placements. */ public string PlacedParamName => string.IsNullOrWhiteSpace(_placedParamName) ? "placed" : _placedParamName; + + /** Query parameter name for the final letter grade. */ + public string GradeParamName => + string.IsNullOrWhiteSpace(_gradeParamName) ? "grade" : _gradeParamName; + + /** Query parameter name for the final numeric score. */ + public string ScoreParamName => + string.IsNullOrWhiteSpace(_scoreParamName) ? "score" : _scoreParamName; } diff --git a/Assets/ScriptableObjects/Configs/TreeShareConfig.asset b/Assets/ScriptableObjects/Configs/TreeShareConfig.asset index 968359e..2bcd262 100644 --- a/Assets/ScriptableObjects/Configs/TreeShareConfig.asset +++ b/Assets/ScriptableObjects/Configs/TreeShareConfig.asset @@ -12,6 +12,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 12b30bbd212e049eb9d2fa93b78b1a36, type: 3} m_Name: TreeShareConfig m_EditorClassIdentifier: - _viewerBaseUrl: https://seemytree.netlify.app/view + _viewerBaseUrl: https://seemytree.netlify.app/results _startParamName: start _placedParamName: placed + _gradeParamName: grade + _scoreParamName: score diff --git a/Assets/UI/Style1/ResultScreenController.cs b/Assets/UI/Style1/ResultScreenController.cs index 84782e3..2267dc1 100644 --- a/Assets/UI/Style1/ResultScreenController.cs +++ b/Assets/UI/Style1/ResultScreenController.cs @@ -297,7 +297,7 @@ public async UniTask ShowAsync(RhythmScoreTracker score, IMenuInputProvider inpu _treeQrDisplay = GetComponent(); try { - _treeQrDisplay?.PrepareResultQrCode(); + _treeQrDisplay?.PrepareResultQrCode(score); } catch (Exception ex) {