Browse Source

fix conten và bấm play 2 lần

student 1 week ago
parent
commit
a8c79daaa5

+ 13 - 1
Kitty_Fall/Kitty_Fall/Kitty_Fall.Apis/Business/Game/GameBusinessImpl.cs

@@ -661,7 +661,19 @@ namespace Kitty_Fall.Apis.Business.Game
                     .FirstOrDefaultAsync();
 
                 var session = await dbContext.GamePlaySessions
-                    .FirstOrDefaultAsync(x => x.RootTransId == request.transId);
+                    .FirstOrDefaultAsync(x => x.RootTransId == request.transId && x.Msisdn == msisdn);
+
+                // A completed/abandoned run must never be reopened with its old transId.
+                // Retries are idempotent only while the same run is still active.
+                if (session != null && session.Status != 1)
+                {
+                    return CommonLogic.BuildResponse(
+                        url,
+                        json,
+                        CommonErrorCode.Error,
+                        Lang.errorOccurred,
+                        new UserGameLevelResultData { reason = "SESSION_CLOSED" });
+                }
 
                 // Tao phien choi khi user bam Play Now lan dau.
                 if (session == null)

+ 24 - 0
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Controllers/GameController.cs

@@ -7,6 +7,7 @@ namespace Kitty_Fall.Website.Controllers
 {
     public class GameController : Controller
     {
+        private const string CompletedGameTransIdSessionKey = "completedGameTransId";
         private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(GameController));
         private readonly IConfiguration _configuration;
 
@@ -20,7 +21,24 @@ namespace Kitty_Fall.Website.Controllers
         {
             try
             {
+                var completedTransId = HttpContext.Session.GetString(CompletedGameTransIdSessionKey);
+                if (!string.IsNullOrWhiteSpace(request.transId)
+                    && string.Equals(request.transId, completedTransId, StringComparison.Ordinal))
+                {
+                    request.transId = Guid.NewGuid().ToString("N");
+                }
+
                 var apiResult = await SendGameApiAsync(request, UrlConstant.GameStartSessionUrl);
+                if (apiResult.errorCode != "0"
+                    && string.Equals(apiResult.data?.reason, "SESSION_CLOSED", StringComparison.OrdinalIgnoreCase))
+                {
+                    // The browser can still hold the completed run's ID (for example
+                    // after iframe navigation/cache). Start a genuinely new run once;
+                    // never reuse or reopen the closed API session.
+                    request.transId = Guid.NewGuid().ToString("N");
+                    apiResult = await SendGameApiAsync(request, UrlConstant.GameStartSessionUrl);
+                }
+
                 if (apiResult.errorCode == "0" && apiResult.data != null)
                 {
                     var maxLevel = await GetTodayMaxLevelAsync(request);
@@ -60,6 +78,11 @@ namespace Kitty_Fall.Website.Controllers
                 var apiResult = await SendGameApiAsync(request, UrlConstant.GameSaveLevelResultUrl);
                 if (apiResult.data != null)
                 {
+                    if (request.gameOver != 0 && apiResult.errorCode == "0")
+                    {
+                        HttpContext.Session.SetString(CompletedGameTransIdSessionKey, request.transId ?? "");
+                    }
+
                     return Json(new
                     {
                         point = apiResult.data.point,
@@ -105,6 +128,7 @@ namespace Kitty_Fall.Website.Controllers
                 if (apiResult.errorCode == "0" && apiResult.data != null)
                 {
                     HttpContext.Session.SetComplexData("totalTurn", (long)apiResult.data.totalTurn);
+                    HttpContext.Session.SetString(CompletedGameTransIdSessionKey, request.transId ?? "");
                 }
                 var payload = JsonSerializer.Serialize(new
                 {

+ 2 - 2
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Language/Lang.vi.resx

@@ -142,10 +142,10 @@
     <value>နေ့စဉ်ပက်ကေ့ဂျ်</value>
   </data>
   <data name="GetFiveTurnsEveryDay" xml:space="preserve">
-    <value>အလှည့် ပက်ကေ့ဂျ် တစ်ခု ရွေးချယ်ပါ</value>
+    <value>စာရင်းသွင်းပြီး ၅ လှည့်ရယူလိုက်ပါ</value>
   </data>
   <data name="SubscriptionAutoRenewDaily" xml:space="preserve">
-    <value>စာရင်းသွင်းမှုကို နေ့စဉ် အလိုအလျောက် သက်တမ်းတိုးပါ</value>
+    <value>နေ့စဥ်အလိုအလျောက် သက်တမ်းတိုးပါမည်။</value>
   </data>
   <data name="SubscribeNow" xml:space="preserve">
     <value>အလှည့်ဝယ်ရန်</value>

+ 1 - 1
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Views/DailyWinners/Index.cshtml

@@ -44,7 +44,7 @@
                     <defs>
                         <path id="daily-winner-title-path" d="M 58 44 Q 160 15 262 44" />
                     </defs>
-                    <text text-anchor="middle" textLength="175" lengthAdjust="spacingAndGlyphs">
+                    <text text-anchor="middle" textLength="190" lengthAdjust="spacing">
                         <textPath href="#daily-winner-title-path" startOffset="50%">@Lang.DailyWinnerList</textPath>
                     </text>
                 </svg>

+ 3 - 3
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Views/Play/Index.cshtml

@@ -56,7 +56,7 @@
                         <span>@Lang.FewerObstacles</span>
                         <span>@Lang.EasierToCompleteLevels</span>
                         <span>@Lang.StandardScoreRewards</span>
-                        <em>@Lang.Rewards: <b>+10-50</b> @Lang.Points</em>
+                        @* <em>@Lang.Rewards: <b>+10-50</b> @Lang.Points</em> *@
                     </span>
                 </button>
 
@@ -70,7 +70,7 @@
                         <span>@Lang.MoreObstacles</span>
                         <span>@Lang.RequiresBetterSkills</span>
                         <span>@Lang.HigherScoreRewards</span>
-                        <em>@Lang.Rewards: <b>+20-100</b> @Lang.Points</em>
+                        @* <em>@Lang.Rewards: <b>+20-100</b> @Lang.Points</em> *@
                     </span>
                 </button>
 
@@ -84,7 +84,7 @@
                         <span>@Lang.MostChallengingLevels</span>
                         <span>@Lang.MaximumToCompleteLevels</span>
                         <span>@Lang.ClimbToLeaderboard</span>
-                        <em>@Lang.Rewards: <b>+100-200</b> @Lang.Points</em>
+                        @* <em>@Lang.Rewards: <b>+100-200</b> @Lang.Points</em> *@
                     </span>
                 </button>
             </div>

+ 27 - 0
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/css/all.min.css

@@ -5306,6 +5306,33 @@ html[lang="my"] .result-benefits {
     white-space: normal;
 }
 
+/* Myanmar glyphs are taller and phrases do not always expose convenient wrap
+   points. Keep the localized package copy inside its grid column and card. */
+html[lang="my"] .package-copy {
+    width: auto;
+    min-width: 0;
+    padding-right: 6px;
+}
+
+html[lang="my"] .package-title {
+    height: 22px;
+    margin-bottom: 1px;
+}
+
+html[lang="my"] .package-title h2 {
+    max-width: 100%;
+    font-size: 13px;
+    line-height: 1.25;
+    overflow-wrap: anywhere;
+}
+
+html[lang="my"] .package-copy p {
+    max-width: 100%;
+    font-size: 10px;
+    line-height: 1.25;
+    overflow-wrap: anywhere;
+}
+
 html[lang="my"] .result-benefits,
 html[lang="my"] .result-benefit {
     height: auto;

+ 27 - 0
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/css/input.css

@@ -5306,6 +5306,33 @@ html[lang="my"] .result-benefits {
     white-space: normal;
 }
 
+/* Myanmar glyphs are taller and phrases do not always expose convenient wrap
+   points. Keep the localized package copy inside its grid column and card. */
+html[lang="my"] .package-copy {
+    width: auto;
+    min-width: 0;
+    padding-right: 6px;
+}
+
+html[lang="my"] .package-title {
+    height: 22px;
+    margin-bottom: 1px;
+}
+
+html[lang="my"] .package-title h2 {
+    max-width: 100%;
+    font-size: 13px;
+    line-height: 1.25;
+    overflow-wrap: anywhere;
+}
+
+html[lang="my"] .package-copy p {
+    max-width: 100%;
+    font-size: 10px;
+    line-height: 1.25;
+    overflow-wrap: anywhere;
+}
+
 html[lang="my"] .result-benefits,
 html[lang="my"] .result-benefit {
     height: auto;

+ 15 - 0
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/js/all.min.js

@@ -320,6 +320,18 @@ const initKittyFall = () => {
             playGameRoot.dataset.totalTurn = String(Math.max(0, Math.round(totalTurn)));
         };
 
+        // A transId identifies one complete run, not one level. Keep it while the
+        // player advances inside the iframe and rotate it only after that run ends.
+        const prepareNextRun = () => {
+            if (globalThis.crypto?.randomUUID) {
+                playGameRoot.dataset.transId = globalThis.crypto.randomUUID().replaceAll("-", "");
+                return;
+            }
+
+            const randomPart = () => Math.random().toString(16).slice(2).padEnd(16, "0");
+            playGameRoot.dataset.transId = `${Date.now().toString(16)}${randomPart()}${randomPart()}`.slice(0, 32);
+        };
+
         const addLevelReward = (data) => {
             const rewardType = String(data?.rewardType || "").toUpperCase();
             const rewardValue = toNumber(data?.rewardValue);
@@ -381,6 +393,7 @@ const initKittyFall = () => {
                 console.error("Save game over error:", error);
             } finally {
                 closeEmbeddedGame();
+                prepareNextRun();
                 showGameOverSummary();
                 finishingGame = false;
             }
@@ -420,6 +433,7 @@ const initKittyFall = () => {
                 setRunSummary(event.data);
                 updateTotalTurn(event.data.totalTurn);
                 closeEmbeddedGame();
+                prepareNextRun();
                 showGameOverSummary();
             }
         });
@@ -463,6 +477,7 @@ const initKittyFall = () => {
                     return;
                 }
 
+                if (result.transId) playGameRoot.dataset.transId = String(result.transId);
                 updateTotalTurn(result.totalTurn);
                 resetRunRewards();
                 gameStarted = true;

+ 15 - 0
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/js/input.js

@@ -320,6 +320,18 @@ const initKittyFall = () => {
             playGameRoot.dataset.totalTurn = String(Math.max(0, Math.round(totalTurn)));
         };
 
+        // A transId identifies one complete run, not one level. Keep it while the
+        // player advances inside the iframe and rotate it only after that run ends.
+        const prepareNextRun = () => {
+            if (globalThis.crypto?.randomUUID) {
+                playGameRoot.dataset.transId = globalThis.crypto.randomUUID().replaceAll("-", "");
+                return;
+            }
+
+            const randomPart = () => Math.random().toString(16).slice(2).padEnd(16, "0");
+            playGameRoot.dataset.transId = `${Date.now().toString(16)}${randomPart()}${randomPart()}`.slice(0, 32);
+        };
+
         const addLevelReward = (data) => {
             const rewardType = String(data?.rewardType || "").toUpperCase();
             const rewardValue = toNumber(data?.rewardValue);
@@ -381,6 +393,7 @@ const initKittyFall = () => {
                 console.error("Save game over error:", error);
             } finally {
                 closeEmbeddedGame();
+                prepareNextRun();
                 showGameOverSummary();
                 finishingGame = false;
             }
@@ -420,6 +433,7 @@ const initKittyFall = () => {
                 setRunSummary(event.data);
                 updateTotalTurn(event.data.totalTurn);
                 closeEmbeddedGame();
+                prepareNextRun();
                 showGameOverSummary();
             }
         });
@@ -463,6 +477,7 @@ const initKittyFall = () => {
                     return;
                 }
 
+                if (result.transId) playGameRoot.dataset.transId = String(result.transId);
                 updateTotalTurn(result.totalTurn);
                 resetRunRewards();
                 gameStarted = true;