using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; public class Leaderboard : MonoBehaviour { GameManager gm; [SerializeField] Transform headerRow; [SerializeField] List Rows; [SerializeField] Transform rankedRow; [SerializeField] Transform rankedPanel; [SerializeField] GameObject instruction; [SerializeField] Vector2 specialPanelLocal, rankedPanelLocal, rankedPanelLocalOnly; [SerializeField] GameObject tgQr, whatsQr; [Header("Маркировка бот/игрок")] [SerializeField] List playerColors; [SerializeField] List botColors; List topRecords; [SerializeField] GameObject RowPrefab; [SerializeField] GameObject RowPrefabRanked; [SerializeField] int MaxRows = 100; [SerializeField] Transform RowsRoot; [SerializeField] Vector2 RowOffset = new Vector2(0, -90); [SerializeField] Vector2 startAnchoredPosition = new Vector2(0, 45); public float accelerationY = 5; public float speedY = 0; public float maxSpeedY = 300; Coroutine slideCoroutine; private string dateFormat = "dd.MM.yy HH:mm"; private void OnDisable() { foreach (var row in Rows) { Destroy(row.gameObject); } Rows.Clear(); if (slideCoroutine != null) StopCoroutine(slideCoroutine); } public void Initialize() { gm = GameManager.instance; rankedPanel.localPosition = rankedPanelLocalOnly; instruction.SetActive(true); int totalRecords = gm.StatsService.GetTotalRecordsCount(); int total = Mathf.Min(MaxRows, totalRecords); topRecords = gm.StatsService.GetTopPlayers(total); //тут надо спавить Ряды SpawnRows(total); ClearRowsText(); for (int i = 0; i < total; i++) { FillRow(i, topRecords[i]); } FillRow(rankedRow, gm.StatsService.GetLatestRecord()); rankedRow.gameObject.SetActive(true); slideCoroutine = StartCoroutine(SlideCoroutine()); speedY = 0; } IEnumerator SlideCoroutine() {//надо еще максимальный слайд рассчитать float minY = startAnchoredPosition.y; float maxY = startAnchoredPosition.y - RowOffset.y *Rows.Count + (RowOffset.y*3); float calculatedOffsetY = minY; List cachedRects = new List(); foreach (Transform row in Rows) { cachedRects.Add(row.GetComponent()); } while (true) { speedY += accelerationY * Time.deltaTime; speedY = Mathf.Clamp(speedY, -maxSpeedY, maxSpeedY); calculatedOffsetY += speedY*Time.deltaTime; calculatedOffsetY = Mathf.Clamp(calculatedOffsetY, minY, maxY); //применить циклом смещение ко всем рядам for (int i = 0; i < Rows.Count; i++) { cachedRects[i].anchoredPosition = startAnchoredPosition + RowOffset * i + Vector2.up * calculatedOffsetY; } yield return null; } } void SpawnRows(int amount) { Rows = new List(); int latestRecordIndex = gm.StatsService.GetRecordRank(gm.StatsService.GetLatestRecord()) - 1; for (int i = 0; i < amount; i++) { GameObject prefab = i == latestRecordIndex ? RowPrefabRanked : RowPrefab; GameObject go = Instantiate(prefab, RowsRoot); RectTransform rect = go.GetComponent(); rect.anchoredPosition = startAnchoredPosition + RowOffset * i; Rows.Add(rect); } } public void ClearRowsText() { for (int i = 0; i < Rows.Count; i++) { for (int j = 0; j < 5; j++) { Rows[i].GetChild(j).GetComponentInChildren().text = "—"; } } for (int j = 0; j < 5; j++) { rankedRow.GetChild(j).GetComponentInChildren().text = "—"; } } private void FillRow(int rowIndex, PlayerStatsRecord record) { Transform row = Rows[rowIndex]; row.GetChild(0).GetComponentInChildren().text = (rowIndex + 1).ToString(); row.GetChild(1).GetComponentInChildren().text = GetMarkedName(record.PlayerName, record.IsBot); row.GetChild(2).GetComponentInChildren().text = secondsToMinutes((int)record.CompletionTimeSec); row.GetChild(3).GetComponentInChildren().text = record.MovesCount.ToString(); row.GetChild(4).GetComponentInChildren().text = record.CompletedAt.ToString(dateFormat); } private void FillRow(Transform row, PlayerStatsRecord record) { int rank = gm.StatsService.GetRecordRank(record); row.GetChild(0).GetComponentInChildren().text = rank.ToString(); row.GetChild(1).GetComponentInChildren().text = GetMarkedName(record.PlayerName, record.IsBot); row.GetChild(2).GetComponentInChildren().text = secondsToMinutes((int)record.CompletionTimeSec); row.GetChild(3).GetComponentInChildren().text = record.MovesCount.ToString(); row.GetChild(4).GetComponentInChildren().text = record.CompletedAt.ToString(dateFormat); } public void DisplayCurrentPlayer(PlayerStatsRecord record) { rankedRow.gameObject.SetActive(true); FillRow(rankedRow, record); } string secondsToMinutes(int seconds) { int minutes = seconds / 60; int remainingSeconds = seconds % 60; return $"{minutes:D2}:{remainingSeconds:D2}"; } //маркируем цветами ботовские рекорды и рекорды игрока. string GetMarkedName(string name, bool isBot) { List colors = isBot ? botColors : playerColors; if (colors == null || colors.Count == 0) return name; int rand = Random.Range(0, colors.Count); string hex = ColorUtility.ToHtmlStringRGB(colors[rand]); return $"{name}*"; } }