local _, ns = ... ns.UI = ns.UI or {} local Amibis = ns.Amibis ns.UI.Frame = {} local ELVUI_BACKDROP_COLOR = { 0.07, 0.07, 0.07 } local ELVUI_BACKDROP_ALPHA = 0.95 local ELVUI_BORDER_COLOR = { 0.23, 0.23, 0.23 } local ELVUI_BORDER_ALPHA = 1.0 local ELVUI_TITLE_BG = { 0.15, 0.15, 0.15 } local COLOR_BIS = { 0.0, 1.0, 0.0 } local COLOR_UPGRADE = { 1.0, 0.82, 0.0 } local COLOR_EMPTY = { 0.6, 0.6, 0.6 } local MainFrame = nil local TitleText = nil local SummaryText = nil local ScrollFrame = nil local SlotRows = {} local MAX_VISIBLE_ROWS = 17 local ROW_HEIGHT = 22 local ROW_SPACING = 24 local function CreateMainFrame() local frame = CreateFrame("Frame", "AmibisMainFrame", UIParent, "BackdropTemplate") frame:SetSize(640, 680) frame:SetFrameStrata("MEDIUM") frame:SetFrameLevel(10) frame:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Buttons\\WHITE8x8", tile = false, tileSize = 0, edgeSize = 1, insets = { left = 0, right = 0, top = 0, bottom = 0 } }) frame:SetBackdropColor(ELVUI_BACKDROP_COLOR[1], ELVUI_BACKDROP_COLOR[2], ELVUI_BACKDROP_COLOR[3], ELVUI_BACKDROP_ALPHA) frame:SetBackdropBorderColor(ELVUI_BORDER_COLOR[1], ELVUI_BORDER_COLOR[2], ELVUI_BORDER_COLOR[3], ELVUI_BORDER_ALPHA) frame:SetMovable(true) frame:EnableMouse(true) frame:RegisterForDrag("LeftButton") frame:SetClampedToScreen(true) frame:SetScript("OnDragStart", function(self) self:StartMoving() end) frame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() Amibis:SaveFramePosition(self) end) frame:SetPoint("CENTER", UIParent, "CENTER", 0, 0) return frame end local function CreateTitleBar(parent) local titleBar = CreateFrame("Frame", nil, parent, "BackdropTemplate") titleBar:SetPoint("TOPLEFT", parent, "TOPLEFT", 0, 0) titleBar:SetPoint("TOPRIGHT", parent, "TOPRIGHT", 0, 0) titleBar:SetHeight(28) titleBar:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Buttons\\WHITE8x8", tile = false, edgeSize = 1, insets = { left = 0, right = 0, top = 0, bottom = 0 } }) titleBar:SetBackdropColor(ELVUI_TITLE_BG[1], ELVUI_TITLE_BG[2], ELVUI_TITLE_BG[3], 1.0) titleBar:SetBackdropBorderColor(ELVUI_BORDER_COLOR[1], ELVUI_BORDER_COLOR[2], ELVUI_BORDER_COLOR[3], 1.0) local titleText = titleBar:CreateFontString(nil, "OVERLAY", "GameFontNormal") titleText:SetPoint("LEFT", titleBar, "LEFT", 8, 0) titleText:SetText("Amibis - Gear Comparison") titleText:SetTextColor(1, 1, 1, 1) local closeBtn = CreateFrame("Button", nil, titleBar) closeBtn:SetSize(20, 20) closeBtn:SetPoint("RIGHT", titleBar, "RIGHT", -4, 0) closeBtn:SetText("X") closeBtn:SetNormalFontObject("GameFontNormal") closeBtn:SetScript("OnClick", function() if MainFrame and MainFrame:IsShown() then MainFrame:Hide() end end) titleBar:EnableMouse(true) titleBar:RegisterForDrag("LeftButton") titleBar:SetScript("OnDragStart", function() parent:StartMoving() end) titleBar:SetScript("OnDragStop", function() parent:StopMovingOrSizing() Amibis:SaveFramePosition(parent) end) return titleBar, titleText end local function CreateSummaryBar(parent, anchor) local bar = CreateFrame("Frame", nil, parent) bar:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -4) bar:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -4) bar:SetHeight(20) local summaryText = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") summaryText:SetPoint("LEFT", bar, "LEFT", 8, 0) summaryText:SetTextColor(0.8, 0.8, 0.8, 1) return bar, summaryText end local function CreateColumnHeaders(parent, anchor) local header = CreateFrame("Frame", nil, parent, "BackdropTemplate") header:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -4) header:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -4) header:SetHeight(18) header:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = 1, insets = { left = 0, right = 0, top = 0, bottom = 0 } }) header:SetBackdropColor(0.12, 0.12, 0.12, 0.5) local slotHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") slotHeader:SetPoint("LEFT", header, "LEFT", 8, 0) slotHeader:SetWidth(55) slotHeader:SetJustifyH("LEFT") slotHeader:SetText("Slot") slotHeader:SetTextColor(0.7, 0.7, 0.7, 1) local equippedHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") equippedHeader:SetPoint("LEFT", slotHeader, "RIGHT", 5, 0) equippedHeader:SetWidth(115) equippedHeader:SetJustifyH("LEFT") equippedHeader:SetText("Equipped") equippedHeader:SetTextColor(0.7, 0.7, 0.7, 1) local bisHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") bisHeader:SetPoint("LEFT", equippedHeader, "RIGHT", 5, 0) bisHeader:SetWidth(115) bisHeader:SetJustifyH("LEFT") bisHeader:SetText("BIS Item") bisHeader:SetTextColor(0.7, 0.7, 0.7, 1) local enchantHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") enchantHeader:SetPoint("LEFT", bisHeader, "RIGHT", 5, 0) enchantHeader:SetWidth(60) enchantHeader:SetJustifyH("LEFT") enchantHeader:SetText("Enchant") enchantHeader:SetTextColor(0.7, 0.7, 0.7, 1) local sourceHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") sourceHeader:SetPoint("LEFT", enchantHeader, "RIGHT", 5, 0) sourceHeader:SetPoint("RIGHT", header, "RIGHT", -8, 0) sourceHeader:SetJustifyH("RIGHT") sourceHeader:SetText("Source") sourceHeader:SetTextColor(0.7, 0.7, 0.7, 1) return header end local function CreateSlotRows(parent, anchor) local container = CreateFrame("Frame", nil, parent) container:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -4) container:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -4) container:SetHeight(MAX_VISIBLE_ROWS * ROW_SPACING) for i = 1, MAX_VISIBLE_ROWS do local row = CreateFrame("Button", nil, container) row:SetPoint("TOPLEFT", container, "TOPLEFT", 0, -(i - 1) * ROW_SPACING) row:SetPoint("TOPRIGHT", container, "TOPRIGHT", 0, -(i - 1) * ROW_SPACING) row:SetHeight(ROW_HEIGHT) row.slotText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") row.slotText:SetPoint("LEFT", row, "LEFT", 8, 0) row.slotText:SetWidth(55) row.slotText:SetJustifyH("LEFT") row.equippedText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") row.equippedText:SetPoint("LEFT", row.slotText, "RIGHT", 5, 0) row.equippedText:SetWidth(115) row.equippedText:SetJustifyH("LEFT") row.equippedText:SetWordWrap(true) row.bisText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") row.bisText:SetPoint("LEFT", row.equippedText, "RIGHT", 5, 0) row.bisText:SetWidth(115) row.bisText:SetJustifyH("LEFT") row.bisText:SetWordWrap(true) row.enchantText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") row.enchantText:SetPoint("LEFT", row.bisText, "RIGHT", 5, 0) row.enchantText:SetWidth(60) row.enchantText:SetJustifyH("LEFT") row.sourceText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") row.sourceText:SetPoint("LEFT", row.enchantText, "RIGHT", 5, 0) row.sourceText:SetPoint("RIGHT", row, "RIGHT", -8, 0) row.sourceText:SetJustifyH("RIGHT") row:SetScript("OnEnter", function(self) if self.bisLink then GameTooltip:SetOwner(self, "ANCHOR_RIGHT") pcall(GameTooltip.SetHyperlink, GameTooltip, self.bisLink) GameTooltip:Show() end end) row:SetScript("OnLeave", function() GameTooltip:Hide() end) row:RegisterForClicks("LeftButtonUp", "RightButtonUp") row:SetScript("OnClick", function(self, button) if self.bisLink and button == "LeftButton" then if IsShiftKeyDown() then ChatEdit_InsertLink(self.bisLink) elseif IsControlKeyDown() then DressUpItemLink(self.bisLink) end end end) SlotRows[i] = row end return container end local StatsPanel = nil local StatsPanelTitle = nil local StatLabels = {} local StatValues = {} local UpgradeLabels = {} local STAT_LABELS = { healing = "+Healing", spellDamage = "+Spell Damage", spellPower = "+Spell Power", intellect = "Intellect", spirit = "Spirit", mp5 = "MP5", haste = "Haste", crit = "Crit", } local STAT_DISPLAY_NAME = { healing = "healing", spellDamage = "spell damage", spellPower = "spell power", intellect = "intellect", spirit = "spirit", mp5 = "mp5", haste = "haste", crit = "crit", } local STATS_COL_W = 60 local STATS_LABEL_W = 80 local STATS_CURRENT_X = STATS_LABEL_W + 16 local STATS_BIS_X = STATS_CURRENT_X + STATS_COL_W local STATS_DIFF_X = STATS_BIS_X + STATS_COL_W local currentStatKeys = {} local function GetStatDisplayName(key) return STAT_DISPLAY_NAME[key] or key end local function FormatUpgradeEntry(idx, upgrade) local text = string.format("%d. %s: ", idx, upgrade.slot) if not upgrade.equipped then return text .. "|cff888888(empty slot)|r" end if not next(upgrade.statDiffs) then return text .. "|cff888888(no stat gain)|r" end local sorted = {} for statKey, diff in pairs(upgrade.statDiffs) do table.insert(sorted, { key = statKey, diff = diff }) end table.sort(sorted, function(a, b) return a.diff > b.diff end) local parts = {} local maxShow = math.min(2, #sorted) for i = 1, maxShow do table.insert(parts, string.format("+%d %s", sorted[i].diff, GetStatDisplayName(sorted[i].key))) end return text .. table.concat(parts, ", ") end local function CreateStatsPanel(parent, anchor) local panel = CreateFrame("Frame", nil, parent, "BackdropTemplate") panel:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -8) panel:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, -8) panel:SetHeight(24) panel:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = 1, insets = { left = 0, right = 0, top = 0, bottom = 0 } }) panel:SetBackdropColor(0.1, 0.1, 0.1, 0.6) panel:SetBackdropBorderColor(0.2, 0.2, 0.2, 1) local title = panel:CreateFontString(nil, "OVERLAY", "GameFontNormal") title:SetPoint("TOPLEFT", panel, "TOPLEFT", 8, -4) title:SetText("Stats Comparison") title:SetTextColor(1, 0.82, 0, 1) StatsPanelTitle = title local currentLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") currentLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_CURRENT_X, -4) currentLabel:SetWidth(STATS_COL_W) currentLabel:SetJustifyH("CENTER") currentLabel:SetText("Current") currentLabel:SetTextColor(0.7, 0.7, 0.7, 1) local bisLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") bisLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_BIS_X, -4) bisLabel:SetWidth(STATS_COL_W) bisLabel:SetJustifyH("CENTER") bisLabel:SetText("BIS") bisLabel:SetTextColor(0.7, 0.7, 0.7, 1) local diffLabel = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") diffLabel:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_DIFF_X, -4) diffLabel:SetWidth(STATS_COL_W) diffLabel:SetJustifyH("CENTER") diffLabel:SetText("Diff") diffLabel:SetTextColor(0.7, 0.7, 0.7, 1) local separator = panel:CreateTexture(nil, "ARTWORK") separator:SetTexture("Interface\\Buttons\\WHITE8x8") separator:SetVertexColor(0.2, 0.2, 0.2, 1) separator:SetPoint("TOPLEFT", panel, "TOPLEFT", 290, 4) separator:SetPoint("BOTTOMLEFT", panel, "BOTTOMLEFT", 290, -4) separator:SetWidth(1) local upgradesTitle = panel:CreateFontString(nil, "OVERLAY", "GameFontNormal") upgradesTitle:SetPoint("TOPLEFT", panel, "TOPLEFT", 300, -4) upgradesTitle:SetText("Top Upgrades") upgradesTitle:SetTextColor(1, 0.82, 0, 1) for i = 1, 3 do local y = -22 - (i - 1) * 16 local label = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") label:SetPoint("TOPLEFT", panel, "TOPLEFT", 300, y) label:SetWidth(320) label:SetJustifyH("LEFT") label:SetText("") label:SetTextColor(COLOR_UPGRADE[1], COLOR_UPGRADE[2], COLOR_UPGRADE[3], 1) UpgradeLabels[i] = label end StatsPanel = panel return panel end local function RebuildStatRows(panel, statKeys) for _, vals in pairs(StatValues) do vals.label:Hide() vals.current:Hide() vals.bis:Hide() vals.diff:Hide() end StatLabels = {} StatValues = {} for i, statKey in ipairs(statKeys) do local y = -22 - (i - 1) * 16 local labelText = STAT_LABELS[statKey] or statKey local label = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") label:SetPoint("TOPLEFT", panel, "TOPLEFT", 8, y) label:SetWidth(STATS_LABEL_W) label:SetJustifyH("RIGHT") label:SetText(labelText) label:SetTextColor(0.6, 0.6, 0.6, 1) local current = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") current:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_CURRENT_X, y) current:SetWidth(STATS_COL_W) current:SetJustifyH("CENTER") current:SetText("0") current:SetTextColor(1, 0.5, 0.5, 1) local bis = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") bis:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_BIS_X, y) bis:SetWidth(STATS_COL_W) bis:SetJustifyH("CENTER") bis:SetText("0") bis:SetTextColor(0, 1, 0, 1) local diff = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") diff:SetPoint("TOPLEFT", panel, "TOPLEFT", STATS_DIFF_X, y) diff:SetWidth(STATS_COL_W) diff:SetJustifyH("CENTER") diff:SetText("0") diff:SetTextColor(1, 1, 1, 1) StatLabels[statKey] = label StatValues[statKey] = { current = current, bis = bis, diff = diff } end panel:SetHeight(#statKeys * 16 + 24) end local function StatKeysEqual(a, b) if #a ~= #b then return false end for i, key in ipairs(a) do if b[i] ~= key then return false end end return true end local function InitializeUI() if MainFrame then return end MainFrame = CreateMainFrame() local titleBar, title = CreateTitleBar(MainFrame) TitleText = title local summaryBar, summary = CreateSummaryBar(MainFrame, titleBar) SummaryText = summary local header = CreateColumnHeaders(MainFrame, summaryBar) local slotContainer = CreateSlotRows(MainFrame, header) CreateStatsPanel(MainFrame, slotContainer) if AmibisCharDB and AmibisCharDB.frameX then MainFrame:ClearAllPoints() Amibis:LoadFramePosition(MainFrame) end MainFrame:Hide() end function ns.UI.Initialize() InitializeUI() end function ns.UI.ToggleFrame() if not MainFrame then InitializeUI() end if MainFrame:IsShown() then MainFrame:Hide() if Amibis._statsRetryTimer then Amibis._statsRetryTimer:Hide() Amibis._statsRetryTimer = nil end else MainFrame:Show() ns.UI.RefreshUI() end end function ns.UI.RefreshUI() if not MainFrame or not MainFrame:IsShown() then return end local data = Amibis:CompareGear() TitleText:SetText(string.format("Amibis - %s %s (%s)", data.class, data.spec or "Unknown", data.phase)) if not data.hasBISList then SummaryText:SetText(string.format("|cffff6666No BIS list available for %s %s in %s|r", data.class, data.spec or "Unknown", data.phase)) for i = 1, 3 do if UpgradeLabels[i] then UpgradeLabels[i]:SetText("") end end for i = 1, MAX_VISIBLE_ROWS do SlotRows[i].slotText:SetText("") SlotRows[i].equippedText:SetText("") SlotRows[i].bisText:SetText("") SlotRows[i].enchantText:SetText("") SlotRows[i].sourceText:SetText("") SlotRows[i].bisLink = nil end return end SummaryText:SetText(string.format("BIS: %d/%d slots", data.bisCount, data.totalSlots)) for i = 1, MAX_VISIBLE_ROWS do local row = SlotRows[i] local slotData = data.slots[i] if slotData then row.slotText:SetText(slotData.slotName) row.slotText:SetTextColor(0.7, 0.7, 0.7, 1) if slotData.isBIS then row.equippedText:SetText(slotData.equipped.link or slotData.equipped.name) row.equippedText:SetTextColor(COLOR_BIS[1], COLOR_BIS[2], COLOR_BIS[3], 1) row.bisText:SetText("|cff00ff00BIS|r") row.bisText:SetTextColor(COLOR_BIS[1], COLOR_BIS[2], COLOR_BIS[3], 1) row.sourceText:SetText(slotData.bis.source) row.sourceText:SetTextColor(0.5, 0.5, 0.5, 1) row.bisLink = slotData.equipped and slotData.equipped.link if slotData.bis.enchant and slotData.equipped then local hasEnchant = false local link = slotData.equipped.link if link then local parts = {} for part in link:gmatch("([^:]+)") do table.insert(parts, part) end local enchantID = tonumber(parts[3]) if enchantID and enchantID > 0 then hasEnchant = true end end if hasEnchant then row.enchantText:SetText("|cff00ff00" .. slotData.bis.enchant.name .. "|r") else row.enchantText:SetText("|cffff6666" .. slotData.bis.enchant.name .. "|r") end elseif slotData.bis.enchant then row.enchantText:SetText("|cffffcc00" .. slotData.bis.enchant.name .. "|r") else row.enchantText:SetText("") end else if slotData.equipped then row.equippedText:SetText(slotData.equipped.link or slotData.equipped.name) row.equippedText:SetTextColor(1, 0.5, 0.5, 1) else row.equippedText:SetText("|cff666666Empty|r") row.equippedText:SetTextColor(COLOR_EMPTY[1], COLOR_EMPTY[2], COLOR_EMPTY[3], 1) end row.bisText:SetText(slotData.bis.name) row.bisText:SetTextColor(COLOR_UPGRADE[1], COLOR_UPGRADE[2], COLOR_UPGRADE[3], 1) row.sourceText:SetText(slotData.bis.source) row.sourceText:SetTextColor(0.5, 0.5, 0.5, 1) if slotData.bis.enchant then row.enchantText:SetText("|cffffcc00" .. slotData.bis.enchant.name .. "|r") else row.enchantText:SetText("") end local _, bisLink = GetItemInfo(slotData.bis.itemID) row.bisLink = bisLink or ("|Hitem:" .. slotData.bis.itemID .. ":0:0:0:0:0:0:0:0|h[" .. slotData.bis.name .. "]|h") end else row.slotText:SetText("") row.equippedText:SetText("") row.bisText:SetText("") row.enchantText:SetText("") row.sourceText:SetText("") row.bisLink = nil end end if data.equippedStats and data.bisStats then local statKeys = Amibis:GetStatKeysForSpec(data.class, data.spec) if not StatKeysEqual(currentStatKeys, statKeys) then RebuildStatRows(StatsPanel, statKeys) currentStatKeys = statKeys end if not data.statsComplete then if StatsPanelTitle then StatsPanelTitle:SetText("Stats Comparison |cff888888(loading...)|r") end for _, statKey in ipairs(statKeys) do local vals = StatValues[statKey] if vals then local current = data.equippedStats[statKey] or 0 vals.current:SetText(current) vals.bis:SetText("|cff888888...|r") vals.diff:SetText("") end end if not Amibis._statsRetryTimer then Amibis._statsRetryTimer = CreateFrame("Frame") Amibis._statsRetryTimer.elapsed = 0 Amibis._statsRetryTimer:SetScript("OnUpdate", function(self, elapsed) self.elapsed = self.elapsed + elapsed if self.elapsed >= 1.5 then self:Hide() Amibis._statsRetryTimer = nil if MainFrame and MainFrame:IsShown() then ns.UI.RefreshUI() end end end) Amibis._statsRetryTimer:Show() end else if StatsPanelTitle then StatsPanelTitle:SetText("Stats Comparison") end for _, statKey in ipairs(statKeys) do local vals = StatValues[statKey] if vals then local current = data.equippedStats[statKey] or 0 local bis = data.bisStats[statKey] or 0 local diff = bis - current vals.current:SetText(current) vals.bis:SetText(bis) if diff > 0 then vals.diff:SetText("+" .. diff) vals.diff:SetTextColor(1, 0.5, 0.5, 1) elseif diff < 0 then vals.diff:SetText(tostring(diff)) vals.diff:SetTextColor(0, 1, 0, 1) else vals.diff:SetText("-") vals.diff:SetTextColor(0.5, 0.5, 0.5, 1) end end end end if not data.statsComplete then if UpgradeLabels[1] then UpgradeLabels[1]:SetText("|cff888888Loading...|r") end for i = 2, 3 do if UpgradeLabels[i] then UpgradeLabels[i]:SetText("") end end elseif data.topUpgrades and #data.topUpgrades > 0 then for i = 1, 3 do if UpgradeLabels[i] then if data.topUpgrades[i] then UpgradeLabels[i]:SetText(FormatUpgradeEntry(i, data.topUpgrades[i])) else UpgradeLabels[i]:SetText("") end end end else if UpgradeLabels[1] then UpgradeLabels[1]:SetText("|cff00ff00All slots are BIS!|r") end for i = 2, 3 do if UpgradeLabels[i] then UpgradeLabels[i]:SetText("") end end end end end local initFrame = CreateFrame("Frame") initFrame:RegisterEvent("PLAYER_LOGIN") initFrame:SetScript("OnEvent", function(self, event) if event == "PLAYER_LOGIN" then InitializeUI() self:UnregisterEvent("PLAYER_LOGIN") end end)