LeaderboardScreen.java

package com.skloch.game;

import com.badlogic.gdx.*;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.utils.StringBuilder;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.skloch.game.AchievementSystem.AchievementSystem;
import com.skloch.game.AchievementSystem.Achievements.Achievements;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;
import java.io.File;
import java.io.FileWriter;
import java.util.Scanner;

public class LeaderboardScreen implements Screen {
    private HustleGame game;
    private Stage leaderboardStage;
    Viewport viewport;
    OrthographicCamera camera;
    String name = "";
    AchievementSystem achievementsystem = AchievementSystem.getInstance();
    Boolean showText = false;
    Table textTable;
    Label title;
    Window textWindow;
    private static ArrayList<Achievements> completedAchievements = new ArrayList<Achievements>();
    TextButton exitButton;
    int Score = 0;
    Table scoresTable;
    public LeaderboardScreen(final HustleGame game, int passScore){

        this.game = game;
        leaderboardStage = new Stage(new FitViewport(game.WIDTH, game.HEIGHT));
        Gdx.input.setInputProcessor(leaderboardStage);

        game.gameScreen.setLeaderboardScreen(this); //for the purpose of setting up name input

        Score = passScore;

        camera = new OrthographicCamera();
        viewport = new FitViewport(game.WIDTH, game.HEIGHT, camera);
        camera.setToOrtho(false, game.WIDTH, game.HEIGHT);

        Window achievementWindow = new Window("", game.skin);
        leaderboardStage.addActor(achievementWindow);

        Table achievementTable = new Table();
        achievementWindow.add(achievementTable);

        Label title = new Label("Achievements", game.skin, "button");
        achievementTable.add(title).padTop(10);
        achievementTable.row();

        //Add achievements list here
        Table achievementlistTable = new Table();
        achievementTable.add(achievementlistTable).prefHeight(380).prefWidth(450);
        achievementTable.row();

        //achievements.
        //get all completed achievements
        completedAchievements = achievementsystem.getCompletedAchievements();

        for (int i = 0; i< completedAchievements.size(); i++){
            if (i > 2){
                achievementlistTable.add(new Label("...And " + (completedAchievements.size() - 3) + " more!", game.skin, "interaction")).padBottom(10);
                break;  //can only display so many achievements in the limited space
            }

            achievementlistTable.add(new Label(completedAchievements.get(i).getName(), game.skin, "button")).padBottom(5);
            achievementlistTable.row();
            achievementlistTable.add(new Label(completedAchievements.get(i).getDescription(), game.skin, "interaction")).padBottom(10);
            achievementlistTable.row();
        }

        TextButton exitButton = new TextButton("Main Menu", game.skin);
        achievementTable.add(exitButton).bottom().width(300).padTop(10);

        exitButton.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                game.soundManager.playButton();
                game.soundManager.overworldMusic.stop();
                dispose();
                game.gameScreen.leaderboardClose();
                achievementsystem.resetAchievements();
                game.setScreen(new MenuScreen(game));
            }
        });

        achievementWindow.pack();

        achievementWindow.setSize(500, 600);

        // Centre the window
        achievementWindow.setX((viewport.getWorldWidth() / 4) - (achievementWindow.getWidth() / 2));
        achievementWindow.setY((viewport.getWorldHeight() / 2) - (achievementWindow.getHeight() / 2));

        leaderboardDisplay();
    }

    public void leaderboardDisplay(){
        Window leaderboardWindow = new Window("", game.skin);
        leaderboardStage.addActor(leaderboardWindow);

        Table leaderboardTable = new Table();
        leaderboardWindow.add(leaderboardTable);

        Label title = new Label("Leaderboard", game.skin, "button");
        leaderboardTable.add(title).padTop(10);
        leaderboardTable.row();

        scoresTable = new Table();
        leaderboardTable.add(scoresTable).prefHeight(380).prefWidth(450);
        leaderboardTable.row();

        calculateScores();

        exitButton = new TextButton("Add Score", game.skin);
        leaderboardTable.add(exitButton).bottom().width(300).padTop(10);

        exitButton.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {

                openTextInput();

                dispose();
            }
        });

        leaderboardWindow.pack();
        leaderboardWindow.setSize(500, 600);

        // Centre the window
        leaderboardWindow.setX((float) ((viewport.getWorldWidth() / 1.33) - (leaderboardWindow.getWidth() / 2)));
        leaderboardWindow.setY((viewport.getWorldHeight() / 2) - (leaderboardWindow.getHeight() / 2));
    }

    public void calculateScores(){
        //calculate top 5 saved scores to display
        ArrayList<String[]> topScores = new ArrayList<>();
        try {
            File scoresFile = new File("assets/SavedScores/Scores.txt");
            Scanner reader = new Scanner(scoresFile);
            while (reader.hasNextLine()){
                String line = reader.nextLine();

                if (line.charAt(0) != '|'){
                    String[] linesplit = line.split(":");
                    topScores.add(linesplit);

                    //remove lowest so it's only the top 10
                    if (topScores.size() > 10){
                        int lowest = 99999; //at minimum set this to higher than the max score
                        int lowestindex = 0;
                        for (int i=0; i< topScores.size(); i++){
                            if (Integer.parseInt(topScores.get(i)[1]) < lowest){
                                lowest = Integer.parseInt(topScores.get(i)[1]);
                                lowestindex = i;
                            }
                        }
                        topScores.remove(lowestindex);
                    }
                }
            }

            //order based on score
            for (int i = 0; i < topScores.size(); i++){
                for (int j = 1; j < (topScores.size() - i); j++){
                    if (Integer.parseInt(topScores.get(j - 1)[1]) > Integer.parseInt(topScores.get(j)[1])){
                        Collections.swap(topScores, j-1, j);
                    }
                }
            }

            //now add to table
            for (int i = topScores.size() - 1; i >= 0; i--) {
                String displaytext = (10 - i) + ": " + topScores.get(i)[0] + " - " + topScores.get(i)[1];
                scoresTable.add(new Label(displaytext, game.skin, "interaction")).padBottom(5);
                scoresTable.row();
            }

            reader.close();
        } catch (FileNotFoundException e){
            e.printStackTrace();
        }
    }

    public void openTextInput(){
        name = "";
        textWindow = new Window("", game.skin);
        leaderboardStage.addActor(textWindow);

        textWindow.pack();
        textWindow.setSize(500, 150);

        // Centre the window
        textWindow.setX((float) ((viewport.getWorldWidth() / 2) - (textWindow.getWidth() / 2)));
        textWindow.setY((viewport.getWorldHeight() / 2) - (textWindow.getHeight() / 2));

        textTable = new Table();
        textWindow.add(textTable);

        title = new Label("enter name", game.skin, "interaction");
        textTable.add(title).padTop(10);
        textTable.row();

        game.gameScreen.resume(); //activates input adapter to read keyboard
    }


    @Override
    public void render(float delta) {

        ScreenUtils.clear(0, 0, 0, 1);

        game.blueBackground.draw();

        leaderboardStage.act(delta);
        leaderboardStage.draw();

        camera.update();
    }

    /*
     * Correctly resizes the onscreen elements when the window is resized
     * @param width
     * @param height
     */
    @Override
    public void resize(int width, int height) {
        leaderboardStage.getViewport().update(width, height);
        viewport.update(width, height);
    }

    public void nameUpdate(int keycode){
        if (Input.Keys.toString(keycode).length() == 1 && name.length() <= 12){
            name = name + Input.Keys.toString(keycode);
        }
        else if ((Objects.equals(Input.Keys.toString(keycode), "Space") && name.length() <= 12)){
            name = name + " ";
        }
        else if (Objects.equals(Input.Keys.toString(keycode), "Delete") && !name.isEmpty()){
            name = name.substring(0, name.length() - 1);
        }
        else if (Objects.equals(Input.Keys.toString(keycode), "Enter")){
            Gdx.input.setInputProcessor(leaderboardStage);
            textWindow.remove();
            exitButton.remove();

            //write score, note that the try-catch is required by the FileWriter class
            try {
                FileWriter scoreWriter = new FileWriter("assets/SavedScores/Scores.txt", true);
                scoreWriter.write("\n");
                scoreWriter.write(name + ":" + Score);
                scoreWriter.close();
            } catch (IOException e){
                e.printStackTrace();
            }

            scoresTable.clear();
            scoresTable.add(new Label("", game.skin, "interaction")).padBottom(5);
            scoresTable.row(); //padding a space because it looks nicer with this :)
            calculateScores();
        }

        title.setText(name);
    }

    // Other required methods from Screen
    @Override
    public void show() {
    }

    @Override
    public void hide() {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

    @Override
    public void dispose() {
    }

}