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)
{