--- ./default.lua	2024-07-18 00:32:16.000000000 -0300
+++ "../../../../../EtternaEO2/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/default.lua"	2024-09-20 19:01:33.502342900 -0300
@@ -813,92 +813,264 @@
 	The following section first adds the ratioText and the maRatio. Then the paRatio is added and positioned. The right
 	values for maRatio and paRatio are then filled in. Finally ratioText and maRatio are aligned to paRatio.
 	--]]
-	local ratioText, maRatio, paRatio, marvelousTaps, perfectTaps, greatTaps
-	t[#t+1] = Def.ActorFrame {
-		Name = "MAPARatioContainer",
-
-		LoadFont("Common Large") .. {
-			Name = "Text",
-			InitCommand = function(self)
-				ratioText = self
-				self:settextf("%s:", translated_info["MAPARatio"])
-				self:zoom(0.25):halign(1)
+		-- Boolean to check whether shift or alt/backslash is held
+		local shiftHeld = false
+		local altHeld = false
+	
+		t[#t+1] = Def.ActorFrame {
+			OnCommand = function(self)
+				SCREENMAN:GetTopScreen():AddInputCallback(function(event)
+					-- Detect if first or repeated shift press
+					local button = event.DeviceInput.button
+					if button == "DeviceButton_left shift" or button == "DeviceButton_right shift" or button == "DeviceButton_tab" then
+						if event.type == "InputEventType_FirstPress" or event.type == "InputEventType_Repeat" then
+							if not shiftHeld then
+								shiftHeld = true
+								MESSAGEMAN:Broadcast("ShiftPressed")
+							end
+						elseif event.type == "InputEventType_Release" then
+							if shiftHeld then
+								shiftHeld = false
+								MESSAGEMAN:Broadcast("ShiftReleased")
+							end
+						end
+					elseif button == "DeviceButton_left alt" or button == "DeviceButton_right alt" or button == "DeviceButton_backslash" then
+						if event.type == "InputEventType_FirstPress" or event.type == "InputEventType_Repeat" then
+							if not altHeld then
+								altHeld = true
+								MESSAGEMAN:Broadcast("AltPressed")
+							end
+						elseif event.type == "InputEventType_Release" then
+							if altHeld then
+								altHeld = false
+								MESSAGEMAN:Broadcast("AltReleased")
+							end
+						end
+					end
+				end)
 			end
-		},
-		LoadFont("Common Large") .. {
-			Name = "MAText",
-			InitCommand = function(self)
-				maRatio = self
-				self:zoom(0.25):halign(1):diffuse(byJudgment(judges[1]))
+		}
+	
+		-- Function for calculating RA and LA, returns the ratio of ridiculous to marvelous and ludicrous to ridiculous from offset plot in replay.
+		local function calculateRatios(score)
+			-- Get replay depending on whether custom windows were used or not
+			local replay = usingCustomWindows and REPLAYS:GetActiveReplay() or score:GetReplay()
+			replay:LoadAllData()
+			-- Offset and tap note vectors from replay
+			local offsetTable = replay:GetOffsetVector()
+			local typeTable = replay:GetTapNoteTypeVector()
+	
+			if not offsetTable or #offsetTable == 0 or not typeTable or #typeTable == 0 then
+				return -1, -1, -1
 			end
-		},
-		LoadFont("Common Large") .. {
-			Name = "PAText",
-			InitCommand = function(self)
-				paRatio = self
-				self:xy(frameWidth + frameX, frameY + 210)
-				self:zoom(0.25)
-				self:halign(1)
-				self:diffuse(byJudgment(judges[2]))
-
-				marvelousTaps = score:GetTapNoteScore(judges[1])
-				perfectTaps = score:GetTapNoteScore(judges[2])
-				greatTaps = score:GetTapNoteScore(judges[3])
-				self:playcommand("Set")
-			end,
-			SetCommand = function(self)
-
-				-- Fill in maRatio and paRatio
-				maRatio:settextf("%.1f:1", marvelousTaps / perfectTaps)
-				paRatio:settextf("%.1f:1", perfectTaps / greatTaps)
-
-				-- Align ratioText and maRatio to paRatio (self)
-				maRatioX = paRatio:GetX() - paRatio:GetZoomedWidth() - 10
-				maRatio:xy(maRatioX, paRatio:GetY())
-
-				ratioTextX = maRatioX - maRatio:GetZoomedWidth() - 10
-				ratioText:xy(ratioTextX, paRatio:GetY())
-				if score:GetChordCohesion() == true then
-					maRatio:maxwidth(maRatio:GetZoomedWidth()/0.25)
-					self:maxwidth(self:GetZoomedWidth()/0.25)
-					ratioText:maxwidth(capWideScale(get43size(65), 85)/0.27)
+	
+			-- Define judgement windows
+			local window = usingCustomWindows and getCurrentCustomWindowConfigJudgmentWindowTable() or {
+				TapNoteScore_W1 = 22.5 * ms.JudgeScalers[judge], -- j4 marv
+				TapNoteScore_W2 = 45 * ms.JudgeScalers[judge],   -- j4 perf
+				TapNoteScore_W3 = 90 * ms.JudgeScalers[judge],   -- j4 g
+			}
+			-- Define RA and LA thresholds
+			window["TapNoteScore_W0"] = window["TapNoteScore_W1"] / 2 -- ra threshold
+			window["TapNoteScore_W-1"] = window["TapNoteScore_W0"] / 2 -- la threshold
+	
+			local laThreshold = window["TapNoteScore_W-1"]
+			local raThreshold = window["TapNoteScore_W0"]
+			local marvThreshold = window["TapNoteScore_W1"] -- marv
+	
+			local ludic = 0
+			local ridicLA = 0
+			local ridic = 0
+			local marvRA = 0
+	
+			-- Iterate over offset table
+			for i, o in ipairs(offsetTable) do
+				-- Check if note is tap or hold
+				if typeTable[i] == "TapNoteType_Tap" or typeTable[i] == "TapNoteType_HoldHead" then
+					local off = math.abs(o)
+					if off <= raThreshold then
+						ridic = ridic + 1
+					elseif off <= marvThreshold then
+						marvRA = marvRA + 1
+					end
+					if off <= laThreshold then
+						ludic = ludic + 1
+					elseif off <= raThreshold then
+						ridicLA = ridicLA + 1
+					end
+				end
+			end
+	
+			-- Return ratios, ridic count, and marv count
+			local ridiculousAttack = ridic / marvRA
+			local ludicrousAttack = ludic / ridicLA
+			return ridiculousAttack, ludicrousAttack, ridicLA, marvRA
+		end
+	
+		--[[
+		The following section first adds the ratioText, laRatio, raRatio, maRatio, and paRatio. Then the correct values are filled in.
+		When shift or alt/backslash is held, the display changes accordingly.
+		--]]
+		local ratioText, raRatio, laRatio, maRatio, paRatio, marvelousTaps, perfectTaps, greatTaps
+		t[#t+1] = Def.ActorFrame {
+			Name = "MAPARatioContainer",
+	
+			LoadFont("Common Large") .. {
+				Name = "Text",
+				InitCommand = function(self)
+					ratioText = self
+					self:settextf("%s:", translated_info["MAPARatio"])
+					self:zoom(0.25):halign(1)
 				end
-			end,
-			CodeMessageCommand = function(self, params)
-				if usingCustomWindows then
-					return
+			},
+			LoadFont("Common Large") .. {
+				Name = "LAText",
+				InitCommand = function(self)
+					laRatio = self
+					self:settextf("%.2f:1", 0)
+					self:zoom(0.25):halign(1):rainbow() -- Rainbow cuz it's LA man come on
+					self:visible(false)
 				end
-
-				if params.Name == "PrevJudge" or params.Name == "NextJudge" then
-						marvelousTaps = getRescoredJudge(dvt, judge, 1)
-						perfectTaps = getRescoredJudge(dvt, judge, 2)
-						greatTaps = getRescoredJudge(dvt, judge, 3)
-					self:playcommand("Set")
+			},
+			LoadFont("Common Large") .. {
+				Name = "RAText",
+				InitCommand = function(self)
+					raRatio = self
+					self:settextf("%.2f:1", 0)
+					self:zoom(0.25):halign(1)  -- No color, user can set whatever they want here. AAAAA is white so I left as white
+					self:visible(false)
 				end
-				if params.Name == "ResetJudge" then
+			},
+			LoadFont("Common Large") .. {
+				Name = "MAText",
+				InitCommand = function(self)
+					maRatio = self
+					self:zoom(0.25):halign(1):diffuse(byJudgment(judges[1]))
+				end
+			},
+			LoadFont("Common Large") .. {
+				Name = "PAText",
+				InitCommand = function(self)
+					paRatio = self
+					self:xy(frameWidth + frameX, frameY + 210)
+					self:zoom(0.25)
+					self:halign(1)
+					self:diffuse(byJudgment(judges[2]))
+	
 					marvelousTaps = score:GetTapNoteScore(judges[1])
 					perfectTaps = score:GetTapNoteScore(judges[2])
 					greatTaps = score:GetTapNoteScore(judges[3])
 					self:playcommand("Set")
-				end
-			end,
-			ForceWindowMessageCommand = function(self)
-				marvelousTaps = getRescoredJudge(dvt, judge, 1)
-				perfectTaps = getRescoredJudge(dvt, judge, 2)
-				greatTaps = getRescoredJudge(dvt, judge, 3)
-				self:playcommand("Set")
-			end,
-			ScoreChangedMessageCommand = function(self)
-				self:playcommand("ForceWindow")
-			end,
-			LoadedCustomWindowMessageCommand = function(self)
-				marvelousTaps = lastSnapshot:GetJudgments()["W1"]
-				perfectTaps = lastSnapshot:GetJudgments()["W2"]
-				greatTaps = lastSnapshot:GetJudgments()["W3"]
-				self:playcommand("Set")
-			end,
-		},
-	}
+				end,
+				SetCommand = function(self)
+					-- Fill in raRatio, laRatio, maRatio, and paRatio
+					local ridiculousAttack, ludicrousAttack, ridics, marvs = calculateRatios(score)
+					maRatio:settextf("%.1f:1", marvelousTaps / perfectTaps)
+					paRatio:settextf("%.1f:1", perfectTaps / greatTaps)
+					raRatio:settextf("%.2f:1", ridiculousAttack)
+					laRatio:settextf("%.2f:1", ludicrousAttack)
+	
+					-- Align with where paRatio was and move things accordingly
+					if altHeld then
+						-- Show LA/RA ratios
+						laRatio:visible(true)
+						raRatio:visible(true)
+						maRatio:visible(false)
+						paRatio:visible(false)
+	
+						raRatio:settextf("%.2f:1", ridics / marvs) -- ridic:marv
+						raRatio:xy(paRatio:GetX(), paRatio:GetY())
+						local laRatioX = raRatio:GetX() - raRatio:GetZoomedWidth() - 10
+						laRatio:xy(laRatioX, raRatio:GetY())
+						local ratioTextX = laRatioX - laRatio:GetZoomedWidth() - 10
+						ratioText:xy(ratioTextX, raRatio:GetY())
+	
+						ratioText:settextf("LA/RA ratio:")
+					elseif shiftHeld then
+						-- Show RA/MA ratios
+						raRatio:visible(true)
+						laRatio:visible(false)
+						maRatio:visible(true)
+						paRatio:visible(false)
+	
+						maRatio:settextf("%.1f:1", marvs / perfectTaps) -- marv:perf
+						raRatio:xy(paRatio:GetX() - maRatio:GetZoomedWidth() - 10, paRatio:GetY())
+						maRatio:xy(paRatio:GetX(), paRatio:GetY())
+						local ratioTextX = raRatio:GetX() - raRatio:GetZoomedWidth() - 10
+						ratioText:xy(ratioTextX, paRatio:GetY())
+	
+						ratioText:settextf("RA/MA ratio:")
+					else
+						-- Show MA/PA ratios
+						raRatio:visible(false)
+						laRatio:visible(false)
+						maRatio:visible(true)
+						paRatio:visible(true)
+	
+						maRatio:settextf("%.1f:1", marvelousTaps / perfectTaps) -- marv:perf
+						local maRatioX = paRatio:GetX() - paRatio:GetZoomedWidth() - 10
+						maRatio:xy(maRatioX, paRatio:GetY())
+						local ratioTextX = maRatioX - maRatio:GetZoomedWidth() - 10
+						ratioText:xy(ratioTextX, paRatio:GetY())
+	
+						ratioText:settextf("%s:", translated_info["MAPARatio"])
+					end
+	
+					if score:GetChordCohesion() == true then
+						maRatio:maxwidth(maRatio:GetZoomedWidth()/0.25)
+						self:maxwidth(self:GetZoomedWidth()/0.25)
+						ratioText:maxwidth(capWideScale(get43size(65), 85)/0.27)
+					end
+				end,
+	
+				ShiftPressedMessageCommand = function(self)
+					self:playcommand("Set")
+				end,
+				ShiftReleasedMessageCommand = function(self)
+					self:playcommand("Set")
+				end,
+				AltPressedMessageCommand = function(self)
+					self:playcommand("Set")
+				end,
+				AltReleasedMessageCommand = function(self)
+					self:playcommand("Set")
+				end,
+	
+				CodeMessageCommand = function(self, params)
+					if usingCustomWindows then
+						return
+					end
+	
+					if params.Name == "PrevJudge" or params.Name == "NextJudge" then
+						marvelousTaps = getRescoredJudge(dvt, judge, 1)
+						perfectTaps = getRescoredJudge(dvt, judge, 2)
+						greatTaps = getRescoredJudge(dvt, judge, 3)
+						self:playcommand("Set")
+					end
+					if params.Name == "ResetJudge" then
+						marvelousTaps = score:GetTapNoteScore(judges[1])
+						perfectTaps = score:GetTapNoteScore(judges[2])
+						greatTaps = score:GetTapNoteScore(judges[3])
+						self:playcommand("Set")
+					end
+				end,
+				ForceWindowMessageCommand = function(self)
+					marvelousTaps = getRescoredJudge(dvt, judge, 1)
+					perfectTaps = getRescoredJudge(dvt, judge, 2)
+					greatTaps = getRescoredJudge(dvt, judge, 3)
+					self:playcommand("Set")
+				end,
+				ScoreChangedMessageCommand = function(self)
+					self:playcommand("ForceWindow")
+				end,
+				LoadedCustomWindowMessageCommand = function(self)
+					marvelousTaps = lastSnapshot:GetJudgments()["W1"]
+					perfectTaps = lastSnapshot:GetJudgments()["W2"]
+					greatTaps = lastSnapshot:GetJudgments()["W3"]
+					self:playcommand("Set")
+				end,
+			},
+		}
 
 	local radars = {"Holds", "Mines", "Rolls", "Lifts", "Fakes"}
 	local radars_translated = {
