package com.example.memorygameone;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

public class DB extends SQLiteOpenHelper {

    public static final String DATABASE_NAME = "games.db";
    public static final int DATABASE_VERSION = 1;
    private DatabaseReference leaderboardRef;

    // Table for the original memory game
    public static final String MEMORY_GAME_TABLE = "memory_game_statistics";
    public static final String COL_ID = "ID";
    public static final String COL_NICKNAME = "NICKNAME";
    public static final String COL_DIFFICULTY = "DIFFICULTY";
    public static final String COL_BEST_TIME_MEMORY = "BEST_TIME_MEMORY";
    public static final String COL_BEST_TIME_SCORE_MEMORY = "BEST_TIME_SCORE_MEMORY";
    public static final String COL_BEST_SCORE_MEMORY = "BEST_SCORE_MEMORY";
    public static final String COL_BEST_SCORE_TIME_MEMORY = "BEST_SCORE_TIME_MEMORY";

    // Table for the reaction game
    public static final String REACTION_GAME_TABLE = "reaction_game_statistics";
    public static final String COL_BEST_REACTION_TIME = "BEST_REACTION_TIME";

    // Table for the pair matching game
    public static final String PAIR_MATCHING_TABLE = "pair_matching_statistics";
    public static final String COL_BEST_MOVES = "BEST_MOVES";
    public static final String COL_BEST_TIME = "BEST_TIME";
    public static final String COL_FASTEST_MOVES = "FASTEST_MOVES";
    public static final String COL_FASTEST_TIME = "FASTEST_TIME";

    public DB(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        leaderboardRef = FirebaseDatabase.getInstance().getReference("leaderboard");
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        // Create table for memory game
        db.execSQL("CREATE TABLE " + MEMORY_GAME_TABLE + " (" +
                COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_NICKNAME + " TEXT, " +
                COL_DIFFICULTY + " TEXT, " +
                COL_BEST_TIME_MEMORY + " INTEGER, " +
                COL_BEST_TIME_SCORE_MEMORY + " INTEGER, " +
                COL_BEST_SCORE_MEMORY + " INTEGER, " +
                COL_BEST_SCORE_TIME_MEMORY + " INTEGER)");


        // Create table for reaction game
        db.execSQL("CREATE TABLE " + REACTION_GAME_TABLE + " (" +
                COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_NICKNAME + " TEXT, " +
                COL_BEST_REACTION_TIME + " INTEGER)");

        // Create table for pair matching game
        db.execSQL("CREATE TABLE " + PAIR_MATCHING_TABLE + " (" +
                COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_NICKNAME + " TEXT, " +
                COL_BEST_MOVES + " INTEGER, " +
                COL_BEST_TIME + " INTEGER, " +
                COL_FASTEST_MOVES + " INTEGER, " +
                COL_FASTEST_TIME + " INTEGER)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older tables if existed
        db.execSQL("DROP TABLE IF EXISTS " + MEMORY_GAME_TABLE);
        db.execSQL("DROP TABLE IF EXISTS " + REACTION_GAME_TABLE);
        db.execSQL("DROP TABLE IF EXISTS " + PAIR_MATCHING_TABLE);
        // Create tables again
        onCreate(db);
    }

    // Methods for Memory Game
    public boolean updateMemoryGameStats(String nickname, String difficulty, int newScore, long newTime) {
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM " + MEMORY_GAME_TABLE +
                " WHERE " + COL_NICKNAME + "=? AND " + COL_DIFFICULTY + "=?", new String[]{nickname, difficulty});

        boolean newRecord = false;
        ContentValues values = new ContentValues();

        if (cursor.moveToFirst()) {
            int bestTimeIndex = cursor.getColumnIndex(COL_BEST_TIME_MEMORY);
            int bestTimeScoreIndex = cursor.getColumnIndex(COL_BEST_TIME_SCORE_MEMORY);
            int bestScoreIndex = cursor.getColumnIndex(COL_BEST_SCORE_MEMORY);
            int bestScoreTimeIndex = cursor.getColumnIndex(COL_BEST_SCORE_TIME_MEMORY);

            long bestTime = (bestTimeIndex != -1) ? cursor.getLong(bestTimeIndex) : Long.MAX_VALUE;
            int bestTimeScore = (bestTimeScoreIndex != -1) ? cursor.getInt(bestTimeScoreIndex) : 0;
            int bestScore = (bestScoreIndex != -1) ? cursor.getInt(bestScoreIndex) : 0;
            long bestScoreTime = (bestScoreTimeIndex != -1) ? cursor.getLong(bestScoreTimeIndex) : Long.MAX_VALUE;

            // Compare time
            if (newTime < bestTime) {
                values.put(COL_BEST_TIME_MEMORY, newTime);
                values.put(COL_BEST_TIME_SCORE_MEMORY, newScore);
                newRecord = true;
            }

            // Compare score
            if (newScore > bestScore) {
                values.put(COL_BEST_SCORE_MEMORY, newScore);
                values.put(COL_BEST_SCORE_TIME_MEMORY, newTime);
                newRecord = true;
            }

            // Update database
            if (newRecord) {
                db.update(MEMORY_GAME_TABLE, values, COL_NICKNAME + "=? AND " + COL_DIFFICULTY + "=?", new String[]{nickname, difficulty});
            }
        } else {
            // If the record doesn't exist, create a new one
            values.put(COL_NICKNAME, nickname);
            values.put(COL_DIFFICULTY, difficulty);
            values.put(COL_BEST_TIME_MEMORY, newTime);
            values.put(COL_BEST_TIME_SCORE_MEMORY, newScore);
            values.put(COL_BEST_SCORE_MEMORY, newScore);
            values.put(COL_BEST_SCORE_TIME_MEMORY, newTime);
            db.insert(MEMORY_GAME_TABLE, null, values);
            newRecord = true;
        }

        cursor.close();
        LeaderboardRecord record = new LeaderboardRecord(nickname, difficulty, newScore, newTime);
        leaderboardRef.child(difficulty).push().setValue(record);

        return newRecord;
    }


    public Cursor getMemoryGameStats(String nickname, String difficulty) {
        SQLiteDatabase db = this.getReadableDatabase();
        return db.rawQuery("SELECT * FROM " + MEMORY_GAME_TABLE +
                " WHERE " + COL_NICKNAME + "=? AND " + COL_DIFFICULTY + "=?", new String[]{nickname, difficulty});
    }

    // Methods for Reaction Game
    public boolean updateReactionGameStats(String nickname, int reactionTime) {
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery("SELECT " + COL_BEST_REACTION_TIME + " FROM " + REACTION_GAME_TABLE +
                " WHERE " + COL_NICKNAME + "=?", new String[]{nickname});
        boolean newRecord = false;

        if (cursor.moveToFirst()) {
            int bestTime = cursor.getInt(0);
            if (reactionTime < bestTime) {
                ContentValues contentValues = new ContentValues();
                contentValues.put(COL_BEST_REACTION_TIME, reactionTime);
                db.update(REACTION_GAME_TABLE, contentValues, COL_NICKNAME + "=?", new String[]{nickname});
                newRecord = true;
            }
        } else {
            ContentValues contentValues = new ContentValues();
            contentValues.put(COL_NICKNAME, nickname);
            contentValues.put(COL_BEST_REACTION_TIME, reactionTime);
            db.insert(REACTION_GAME_TABLE, null, contentValues);
            newRecord = true;
        }
        cursor.close();
        return newRecord;
    }

    public Cursor getReactionGameStats(String nickname) {
        SQLiteDatabase db = this.getReadableDatabase();
        return db.rawQuery("SELECT " + COL_BEST_REACTION_TIME + " FROM " + REACTION_GAME_TABLE +
                " WHERE " + COL_NICKNAME + "=?", new String[]{nickname});
    }

    // Methods for Pair Matching Game
    public boolean updatePairMatchingStats(String nickname, int moves, long time) {
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM " + PAIR_MATCHING_TABLE + " WHERE " + COL_NICKNAME + "=?", new String[]{nickname});

        boolean newRecord = false;
        ContentValues values = new ContentValues();

        if (cursor.moveToFirst()) {
            int bestMovesIndex = cursor.getColumnIndex(COL_BEST_MOVES);
            int bestTimeIndex = cursor.getColumnIndex(COL_BEST_TIME);
            int fastestMovesIndex = cursor.getColumnIndex(COL_FASTEST_MOVES);
            int fastestTimeIndex = cursor.getColumnIndex(COL_FASTEST_TIME);

            int bestMoves = (bestMovesIndex != -1) ? cursor.getInt(bestMovesIndex) : Integer.MAX_VALUE;
            long bestTime = (bestTimeIndex != -1) ? cursor.getLong(bestTimeIndex) : Long.MAX_VALUE;
            int fastestMoves = (fastestMovesIndex != -1) ? cursor.getInt(fastestMovesIndex) : Integer.MAX_VALUE;
            long fastestTime = (fastestTimeIndex != -1) ? cursor.getLong(fastestTimeIndex) : Long.MAX_VALUE;

            if (moves < bestMoves) {
                values.put(COL_BEST_MOVES, moves);
                values.put(COL_BEST_TIME, time);
                newRecord = true;
            }

            if (time < fastestTime) {
                values.put(COL_FASTEST_MOVES, moves);
                values.put(COL_FASTEST_TIME, time);
                newRecord = true;
            }

            if (newRecord) {
                db.update(PAIR_MATCHING_TABLE, values, COL_NICKNAME + "=?", new String[]{nickname});
            }
        } else {
            values.put(COL_NICKNAME, nickname);
            values.put(COL_BEST_MOVES, moves);
            values.put(COL_BEST_TIME, time);
            values.put(COL_FASTEST_MOVES, moves);
            values.put(COL_FASTEST_TIME, time);
            db.insert(PAIR_MATCHING_TABLE, null, values);
            newRecord = true;
        }

        cursor.close();
        return newRecord;
    }

    public Cursor getPairMatchingStats(String nickname) {
        SQLiteDatabase db = this.getReadableDatabase();
        return db.rawQuery("SELECT * FROM " + PAIR_MATCHING_TABLE + " WHERE " + COL_NICKNAME + "=?", new String[]{nickname});
    }
}




package com.example.memorygameone;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Spinner;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;

public class LeaderboardActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private LeaderboardAdapter adapter;
    private List<LeaderboardRecord> leaderboardList;
    private DatabaseReference leaderboardRef;
    private Spinner gameSpinner, difficultySpinner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_leaderboard);

        recyclerView = findViewById(R.id.leaderboardRecyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        leaderboardList = new ArrayList<>();
        adapter = new LeaderboardAdapter(leaderboardList);
        recyclerView.setAdapter(adapter);

        leaderboardRef = FirebaseDatabase.getInstance().getReference("leaderboard");

        gameSpinner = findViewById(R.id.game_spinner);
        difficultySpinner = findViewById(R.id.difficulty_spinner);

        gameSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                loadLeaderboard();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {}
        });

        difficultySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                loadLeaderboard();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {}
        });

        // Начальная загрузка
        loadLeaderboard();
    }

    private void loadLeaderboard() {
        String selectedGame = gameSpinner.getSelectedItem().toString().toLowerCase().replace(" ", "_"); // Преобразование названия игры в формат ключа
        String selectedDifficulty = difficultySpinner.getSelectedItem().toString().toLowerCase();

        Query leaderboardQuery = leaderboardRef.child(selectedGame).child(selectedDifficulty)
                .orderByChild("score").limitToLast(10); // Сортировка по полю score

        leaderboardQuery.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                leaderboardList.clear();
                if (!dataSnapshot.exists()) {
                    Log.d("Leaderboard", "No records found for this game and difficulty.");
                } else {
                    for (DataSnapshot recordSnapshot : dataSnapshot.getChildren()) {
                        LeaderboardRecord record = recordSnapshot.getValue(LeaderboardRecord.class);
                        if (record != null) {
                            leaderboardList.add(0, record); // Добавляем в обратном порядке для отображения лучших сначала
                        }
                    }
                }
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.e("Leaderboard", "Database error: " + databaseError.getMessage());
            }
        });
    }
}



package com.example.memorygameone;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class LeaderboardAdapter extends RecyclerView.Adapter<LeaderboardAdapter.ViewHolder> {
    private List<LeaderboardRecord> leaderboardList;

    public LeaderboardAdapter(List<LeaderboardRecord> leaderboardList) {
        this.leaderboardList = leaderboardList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.leaderboard_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(LeaderboardAdapter.ViewHolder holder, int position) {
        LeaderboardRecord record = leaderboardList.get(position);
        holder.nicknameTextView.setText(record.getNickname());
        holder.scoreTextView.setText(String.valueOf(record.getScore()));
        holder.timeTextView.setText(formatTime(record.getTime()));
    }

    @Override
    public int getItemCount() {
        return leaderboardList.size();
    }

    private String formatTime(long totalSeconds) {
        long minutes = totalSeconds / 60;
        long seconds = totalSeconds % 60;
        return String.format("%d:%02d", minutes, seconds);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView nicknameTextView;
        TextView scoreTextView;
        TextView timeTextView;

        public ViewHolder(View itemView) {
            super(itemView);
            nicknameTextView = itemView.findViewById(R.id.nicknameTextView);
            scoreTextView = itemView.findViewById(R.id.scoreTextView);
            timeTextView = itemView.findViewById(R.id.timeTextView);
        }
    }
}




package com.example.memorygameone;

public class LeaderboardRecord {
    private String nickname;
    private String difficulty;
    private int score;
    private long time;

    // Конструктор без параметров для Firebase
    public LeaderboardRecord() {}

    public LeaderboardRecord(String nickname, String difficulty, int score, long time) {
        this.nickname = nickname;
        this.difficulty = difficulty;
        this.score = score;
        this.time = time;
    }

    // Геттеры и сеттеры
    public String getNickname() { return nickname; }
    public void setNickname(String nickname) { this.nickname = nickname; }

    public String getDifficulty() { return difficulty; }
    public void setDifficulty(String difficulty) { this.difficulty = difficulty; }

    public int getScore() { return score; }
    public void setScore(int score) { this.score = score; }

    public long getTime() { return time; }
    public void setTime(long time) { this.time = time; }
}




package com.example.memorygameone;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Button;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private SoundManager soundManager;
    private FirebaseAuth auth;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        auth = FirebaseAuth.getInstance();

        // Проверяем, вошел ли пользователь
        if (auth.getCurrentUser() == null) {
            startActivity(new Intent(MainActivity.this, LoginActivity.class));
            finish();
        }
        FirebaseApp.initializeApp(this);
        soundManager = SoundManager.getInstance(this);

        SharedPreferences preferences = getSharedPreferences("game_prefs", MODE_PRIVATE);
        boolean isFirstRun = preferences.getBoolean("isFirstRun", true);

        if (isFirstRun) {
            // Go to LoginActivity on the first run
            startActivity(new Intent(MainActivity.this, LoginActivity.class));
            finish();
            preferences.edit().putBoolean("isFirstRun", false).apply();
            return;
        }


        Button btnStartMemoryGame = findViewById(R.id.btn_memory);
        Button btnStartReactionGame = findViewById(R.id.btn_reaction);
        Button btnProfile = findViewById(R.id.btn_profile);
        Button btnStartPairMatchingGame = findViewById(R.id.btn_pair_matching);
        Button btnLeaderboard = findViewById(R.id.btn_leaderboard);
        btnLeaderboard.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, LeaderboardActivity.class);
            startActivity(intent);
        });

        btnStartMemoryGame.setOnClickListener(v -> {
            soundManager.playButtonClickSound();
            Intent intent = new Intent(MainActivity.this, DifficultySelectionActivity.class);
            startActivity(intent);
        });

        btnStartReactionGame.setOnClickListener(v -> {
            soundManager.playButtonClickSound();
            Intent intent = new Intent(MainActivity.this, ReactionGameModeSelection.class);
            startActivity(intent);
        });

        btnProfile.setOnClickListener(v -> {
            soundManager.playButtonClickSound();
            Intent intent = new Intent(MainActivity.this, ProfileActivity.class);
            startActivity(intent);
        });

        btnStartPairMatchingGame.setOnClickListener(v -> {
            soundManager.playButtonClickSound();
            Intent intent = new Intent(MainActivity.this, PairMatchingGame.class);
            startActivity(intent);
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        auth = FirebaseAuth.getInstance();
        FirebaseUser currentUser = auth.getCurrentUser();

        // If user is not logged in, navigate to LoginActivity
        if (currentUser == null) {
            Intent intent = new Intent(MainActivity.this, LoginActivity.class);
            startActivity(intent);
            finish();  // Close MainActivity to prevent going back to it
        }
    }



    @Override
    protected void onPause() {
        super.onPause();
        if (soundManager != null) {
            soundManager.pauseBackgroundMusic();
        }
    }

}



package com.example.memorygameone;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Random;
import android.content.SharedPreferences;
import android.app.AlertDialog;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import androidx.constraintlayout.widget.ConstraintLayout;
import nl.dionsegijn.konfetti.KonfettiView;
import nl.dionsegijn.konfetti.models.Shape;
import nl.dionsegijn.konfetti.models.Size;
public class MemoryGame extends Activity {

    private GridLayout gridLayout;
    private ArrayList<Button> squares;
    private TextView title;
    private TextView level;
    private TextView scoreText;
    private Button startButton;
    private Button nextLevelButton;
    private ArrayList<Button> correctSeq;
    private int currentLevel;
    private int currentScore;
    private int userIndex;
    private int tileCount;
    private String difficulty;
    private Handler handler;
    private DB dbHelper;
    private SharedPreferences preferences;
    private String playerNickname;
    private int attemptsLeft = 3;
    private int currentTilePoints = 50;
    private SoundManager soundManager;

    private TextView timerTextView;
    private Handler timerHandler = new Handler();
    private Runnable timerRunnable;
    private long startTime;
    private long endTime;

    private final int COLOR_BACKGROUND = Color.parseColor("#E6E6FA");
    private final int COLOR_BUTTON_NORMAL = Color.parseColor("#800080");
    private final int COLOR_BUTTON_FLASH = Color.parseColor("#008000");
    private final int COLOR_BUTTON_CORRECT = Color.parseColor("#0000FF");
    private final int COLOR_BUTTON_WRONG = Color.parseColor("#F44336");
    private final int COLOR_TEXT = Color.parseColor("#FFA500");
    private final int COLOR_TILE_NORMAL = Color.parseColor("#FFFFFF");
    private boolean gameStarted = false;
    private KonfettiView konfettiView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_memory_game);
        konfettiView = findViewById(R.id.konfettiView);

        soundManager = SoundManager.getInstance(this);
        gridLayout = findViewById(R.id.gridLayout);

        tileCount = getIntent().getIntExtra("tileCount", 9);
        difficulty = getDifficultyLabel(tileCount);

        dbHelper = new DB(this);
        preferences = getSharedPreferences("game_prefs", MODE_PRIVATE);
        playerNickname = preferences.getString("nickname", "Player");

        ConstraintLayout mainLayout = findViewById(R.id.mainLayout);
        mainLayout.setBackgroundColor(COLOR_BACKGROUND);

        title = findViewById(R.id.title);
        level = findViewById(R.id.level);
        scoreText = findViewById(R.id.score);
        startButton = findViewById(R.id.startBtn);
        nextLevelButton = findViewById(R.id.nextLevelBtn);
        timerTextView = findViewById(R.id.timerTextView);

        startButton.setOnClickListener(v -> startGame());
        nextLevelButton.setOnClickListener(v -> startGame());
        nextLevelButton.setVisibility(View.GONE);

        correctSeq = new ArrayList<>();
        currentLevel = 1;
        currentScore = 0;
        handler = new Handler();

        setupUI();
        setupGameGrid();
        updateUI();

        timerRunnable = new Runnable() {
            @Override
            public void run() {
                long millis = System.currentTimeMillis() - startTime;
                int seconds = (int) (millis / 1000);
                int minutes = seconds / 60;
                seconds = seconds % 60;

                timerTextView.setText(String.format("%d:%02d", minutes, seconds));
                timerHandler.postDelayed(this, 500);
            }
        };
        startButton.setOnClickListener(v -> {
            soundManager.playButtonClickSound();
            startGame();
        });
        nextLevelButton.setOnClickListener(v -> {
            soundManager.playButtonClickSound();
            startGame();
        });
    }

    private void setupUI() {
        title.setTextColor(COLOR_TEXT);
        level.setTextColor(COLOR_TEXT);
        scoreText.setTextColor(COLOR_TEXT);

        startButton.setBackgroundColor(COLOR_BUTTON_NORMAL);
        startButton.setTextColor(COLOR_TEXT);

        nextLevelButton.setBackgroundColor(COLOR_BUTTON_NORMAL);
        nextLevelButton.setTextColor(COLOR_TEXT);
    }

    private String getDifficultyLabel(int tileCount) {
        switch (tileCount) {
            case 4:
                return "easy";
            case 9:
                return "medium";
            case 12:
                return "hard";
            default:
                return "medium";
        }
    }

    private void setupGameGrid() {
        squares = new ArrayList<>();
        gridLayout.removeAllViews();

        int columnCount = (int) Math.sqrt(tileCount);
        gridLayout.setColumnCount(columnCount);

        int screenWidth = getResources().getDisplayMetrics().widthPixels;
        int screenHeight = getResources().getDisplayMetrics().heightPixels;

        int availableWidth = screenWidth - 40;
        int availableHeight = screenHeight - 300;

        int tileSize = Math.min(availableWidth / columnCount, availableHeight / columnCount) - 10;

        for (int i = 0; i < tileCount; i++) {
            Button button = new Button(this);
            button.setId(View.generateViewId());

            GridLayout.LayoutParams params = new GridLayout.LayoutParams();
            params.width = tileSize;
            params.height = tileSize;
            params.setMargins(5, 5, 5, 5);
            button.setLayoutParams(params);

            button.setBackgroundColor(COLOR_TILE_NORMAL);
            button.setTextColor(COLOR_TEXT);
            button.setTextSize(20);

            button.setOnClickListener(this::checkSequence);
            squares.add(button);
            gridLayout.addView(button);
        }
    }

    private void resetTileColors() {
        for (Button button : squares) {
            button.setBackgroundColor(COLOR_TILE_NORMAL);
            button.setText("");
        }
    }

    private void startGame() {
        gameStarted = true;
        isCheckingSequence = false;
        if (currentLevel == 1) {
            startTime = System.currentTimeMillis();
        }
        timerHandler.postDelayed(timerRunnable, 0);
        nextLevelButton.setVisibility(View.GONE);
        if (currentLevel > 2) {
            showVictoryMessage();
            return;
        }

        correctSeq.clear();
        userIndex = 0;
        currentTilePoints = 50;
        title.setText("Запоминай последовательность!");
        level.setText("Уровень " + currentLevel + " | Попыток: " + attemptsLeft);
        disableSquares();
        startButton.setVisibility(View.INVISIBLE);

        resetTileColors();
        showPattern();
    }



    private void showPattern() {
        disableSquares();
        int delay = preferences.getInt("sequence_speed", 700);
        for (int i = 0; i < currentLevel; i++) {
            int finalI = i;
            handler.postDelayed(() -> {
                Random random = new Random();
                int randomIndex = random.nextInt(squares.size());
                Button randomSq = squares.get(randomIndex);
                flashButton(randomSq, false);
                correctSeq.add(randomSq);

                if (finalI == currentLevel - 1) {
                    handler.postDelayed(this::playerTurn, 700);
                }
            }, delay);
            delay += preferences.getInt("sequence_speed", 700);
        }
    }

    private void flashButton(Button button, boolean isPlayerTurn) {
        int color = isPlayerTurn ? COLOR_BUTTON_CORRECT : COLOR_BUTTON_FLASH;
        animateButton(button, color, "");
        soundManager.playButtonClickSound();
    }

    private void playerTurn() {
        enableSquares();
        title.setText("Повтори последовательность");
    }

    private boolean isCheckingSequence = false;
    private void checkSequence(View view) {
        if (!gameStarted || isCheckingSequence) {
            return;
        }

        soundManager.playButtonClickSound();
        isCheckingSequence = true;
        Button clickedButton = (Button) view;

        if (clickedButton == correctSeq.get(userIndex)) {
            soundManager.playCorrectSound();
            animateButton(clickedButton, COLOR_BUTTON_CORRECT, "✔");

            userIndex++;
            level.setText(userIndex + "/" + currentLevel);

            currentScore += currentTilePoints;
            currentTilePoints += 25;

            updateUI();

            if (userIndex == currentLevel) {
                currentLevel++;
                soundManager.playLevelUpSound();
                handler.postDelayed(this::startNextLevel, 1000);
            } else {
                handler.postDelayed(() -> {
                    isCheckingSequence = false;
                    enableSquares();
                }, 500);
            }
        } else {
            soundManager.playWrongSound();
            animateButton(clickedButton, COLOR_BUTTON_WRONG, "✖");

            currentScore = 0;
            updateUI();

            attemptsLeft--;
            if (attemptsLeft > 0) {
                handler.postDelayed(this::resetLevel, 1000);
            } else {
                handler.postDelayed(this::gameOver, 1000);
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (gameStarted) {
            timerHandler.postDelayed(timerRunnable, 0);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        timerHandler.removeCallbacks(timerRunnable);
    }


    private void startNextLevel() {
        title.setText("Уровень пройден! Готовы к следующему?");
        nextLevelButton.setVisibility(View.VISIBLE);
        disableSquares();
        isCheckingSequence = false;
    }

    private void resetLevel() {
        title.setText("Новая последовательность! Попыток: " + attemptsLeft);
        disableSquares();
        isCheckingSequence = false;
        handler.postDelayed(this::startGame, 1000);
    }

    private void gameOver() {
        gameStarted = false;
        isCheckingSequence = false;
        timerHandler.removeCallbacks(timerRunnable);
        title.setText("Игра окончена!");

        endTime = System.currentTimeMillis();
        long totalTime = (endTime - startTime) / 1000;

        disableSquares();
        startButton.setVisibility(View.VISIBLE);

        boolean isNewRecord = dbHelper.updateMemoryGameStats(playerNickname, difficulty, currentScore, totalTime);

        if (isNewRecord) {
            soundManager.playNewRecordSound();
            showConfetti();
        } else {
            soundManager.playDefeatSound();
        }

        showGameOverDialog(isNewRecord);
    }

    private void showGameOverDialog(boolean isNewRecord) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AlertDialogCustom);
        String message = isNewRecord ?
                "Поздравляем! Вы установили новый рекорд!\n" :
                "Вы исчерпали все попытки. ";
        message += "Хотите попробовать снова или вернуться в главное меню?";

        builder.setTitle("Игра окончена!")
                .setMessage(message)
                .setPositiveButton("Попробовать снова", (dialog, which) -> {
                    currentLevel = 1;
                    currentScore = 0;
                    currentTilePoints = 50;
                    attemptsLeft = 3;
                    startGame();
                })
                .setNegativeButton("Главное меню", (dialog, which) -> {
                    Intent intent = new Intent(MemoryGame.this, MainActivity.class);
                    startActivity(intent);
                    finish();
                })
                .setCancelable(false)
                .show();
    }


    private void showVictoryMessage() {
        endTime = System.currentTimeMillis();
        long totalTime = (endTime - startTime) / 1000;

        boolean isNewRecord = dbHelper.updateMemoryGameStats(playerNickname, difficulty, currentScore, totalTime);

        if (isNewRecord) {
            soundManager.playNewRecordSound();
            showConfetti();
        } else {
            soundManager.playVictorySound();
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AlertDialogCustom);
        String message = isNewRecord ?
                "Поздравляем! Вы установили новый рекорд!\n" :
                "Вы успешно прошли игру!\n";

        builder.setTitle("Поздравляем!")
                .setMessage(message)
                .setPositiveButton("Назад в главное меню", (dialog, which) -> {
                    Intent intent = new Intent(MemoryGame.this, MainActivity.class);
                    startActivity(intent);
                    finish();
                })
                .setCancelable(false)
                .show();
    }


    private void updateUI() {
        scoreText.setText("Очки: " + currentScore);
        level.setText("Уровень: " + currentLevel + " | Попыток: " + attemptsLeft);
    }

    private void enableSquares() {
        for (Button square : squares) {
            square.setClickable(true);
        }
    }

    private void disableSquares() {
        for (Button square : squares) {
            square.setClickable(false);
        }
    }

    private void animateButton(final Button button, int color, String text) {
        button.setBackgroundColor(color);
        button.setText(text);

        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1f, 1.2f, 1f);
        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1f, 1.2f, 1f);
        ObjectAnimator scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(button, scaleX, scaleY);
        scaleAnimator.setDuration(300);
        scaleAnimator.setInterpolator(new AccelerateDecelerateInterpolator());

        scaleAnimator.start();

        handler.postDelayed(() -> {
            button.setBackgroundColor(COLOR_TILE_NORMAL);
            button.setText("");
        }, 500);
    }



    @Override
    protected void onDestroy() {
        super.onDestroy();
        soundManager.release();
    }

    private void showConfetti() {
        konfettiView.build()
                .addColors(Color.YELLOW, Color.GREEN, Color.MAGENTA)
                .setDirection(0.0, 359.0)
                .setSpeed(1f, 5f)
                .setFadeOutEnabled(true)
                .setTimeToLive(2000L)
                .addShapes(Shape.Square.INSTANCE, Shape.Circle.INSTANCE)
                .addSizes(new Size(12, 5f))
                .setPosition(-50f, konfettiView.getWidth() + 50f, -50f, -50f)
                .streamFor(300, 5000L);
    }
}




это была часть моего кода 
мне нужно чтобы в странице Leaderboard показывались рекорды и никнеймы игроков которые эти рекорды сделали на данный момент там выходит просто пустой экран  скажи там же передаются таблицы из локальной базы данных в firebase или нет или нужно создать сначала там базу данных вручную в общем помоги мне корректно реализовать онлайн таблицу лучших результатов среди игроков