gyrodraw/GyroDraw

View on GitHub
app/src/main/java/ch/epfl/sweng/GyroDraw/game/RankingFragment.java

Summary

Maintainability
A
1 hr
Test Coverage
package ch.epfl.sweng.GyroDraw.game;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.ListFragment;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.google.firebase.database.DataSnapshot;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ch.epfl.sweng.GyroDraw.R;
import ch.epfl.sweng.GyroDraw.auth.Account;
import ch.epfl.sweng.GyroDraw.firebase.FbDatabase;
import ch.epfl.sweng.GyroDraw.firebase.OnSuccessValueEventListener;
import ch.epfl.sweng.GyroDraw.home.battleLog.GameResult;
import ch.epfl.sweng.GyroDraw.localDatabase.LocalDbForGameResults;
import ch.epfl.sweng.GyroDraw.localDatabase.LocalDbHandlerForGameResults;
import ch.epfl.sweng.GyroDraw.utils.LayoutUtils;
import ch.epfl.sweng.GyroDraw.utils.RankingUtils;
import ch.epfl.sweng.GyroDraw.utils.SortUtils;
import ch.epfl.sweng.GyroDraw.utils.TypefaceLibrary;

import static ch.epfl.sweng.GyroDraw.firebase.RoomAttributes.FINISHED;
import static ch.epfl.sweng.GyroDraw.firebase.RoomAttributes.RANKING;
import static ch.epfl.sweng.GyroDraw.utils.LayoutUtils.bounceButton;
import static ch.epfl.sweng.GyroDraw.utils.LayoutUtils.isPointInsideView;
import static ch.epfl.sweng.GyroDraw.utils.LayoutUtils.pressButton;

/**
 * A custom {@link ListFragment} used for displaying the final ranking at the end of the game.
 */
public class RankingFragment extends ListFragment {

    private String roomId;

    private Map<String, Integer> finalRanking;

    private Bitmap[] drawings;
    private String[] playerNames;

    private Account account;
    private VotingPageActivity activity;

    public RankingFragment() {
        // Empty constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.ranking_list_fragment, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        ((TextView) getActivity().findViewById(R.id.rankingTitle))
                .setTypeface(TypefaceLibrary.getTypeMuro());

        Button button = getActivity().findViewById(R.id.homeButton);
        button.setTypeface(TypefaceLibrary.getTypeMuro());

        account = Account.getInstance(getActivity().getApplicationContext());

        retrieveFinalRanking();
        setHomeButtonListener();
    }

    /**
     * Sets the attributes of this class.
     *
     * @param roomId      the id of the room.
     * @param drawings    the users drawings.
     * @param playerNames the usernames of the players.
     * @param activity    the activity instantiating the fragment
     */
    public void putExtra(String roomId, Bitmap[] drawings, String[] playerNames,
                         VotingPageActivity activity) {
        this.roomId = roomId;
        this.drawings = drawings.clone();
        this.playerNames = playerNames.clone();
        this.activity = activity;
    }

    private int getIndexForUserName(String username) {
        for (int i = 0; i < this.playerNames.length; i++) {
            if (username.equals(playerNames[i])) {
                return i;
            }
        }
        throw new IllegalArgumentException("Index not found");
    }

    private void retrieveFinalRanking() {
        FbDatabase.getRoomAttribute(roomId, RANKING,
                new OnSuccessValueEventListener() {

                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                        finalRanking = new HashMap<>();
                        for (DataSnapshot ds : dataSnapshot.getChildren()) {
                            if (ds.getValue(Integer.class) != null && ds.getKey() != null) {
                                finalRanking.put(ds.getKey(), ds.getValue(Integer.class));
                            }
                        }

                        // Sort the rankings (stars)
                        Integer[] rankings = (finalRanking.values().toArray(
                                new Integer[0]));
                        Arrays.sort(rankings, Collections.reverseOrder());

                        int rankForUser = 0;
                        if (dataSnapshot.child(account.getUsername()).getValue(int.class) != null) {
                            rankForUser = dataSnapshot.child(account.getUsername())
                                    .getValue(int.class);
                        }

                        Integer[] trophies = RankingUtils.generateTrophiesFromRanking(rankings);
                        Integer[] positions = RankingUtils.generatePositionsFromRanking(rankings);
                        List<String> usernames = SortUtils.sortByValue(finalRanking);

                        int trophiesForUser = trophies[usernames.indexOf(account.getUsername())];

                        Boolean won = usernames.get(0).equals(account.getUsername());
                        updateUserStats(rankForUser, trophiesForUser, won);
                        createAndStoreGameResult(usernames, usernames.indexOf(
                                account.getUsername()), rankForUser, trophiesForUser);

                        String[] tmpUserNames = usernames.toArray(new String[usernames.size()]);
                        ArrayAdapter<String> adapter = new RankingAdapter(getActivity(),
                                tmpUserNames, rankings, trophies, drawings, positions);
                        setListAdapter(adapter);
                        setFinishedCollectingRanking();
                    }
                });
    }

    private void updateUserStats(int starIncrease, int trophiesIncrease, boolean won) {
        account.changeStars(starIncrease);
        account.changeTrophies(trophiesIncrease);
        account.increaseTotalMatches();
        account.changeAverageRating(starIncrease);
        if (won) {
            account.increaseMatchesWon();
        }
    }

    /**
     * Create a game result and save the result into the local database.
     */
    public void createAndStoreGameResult(List<String> names, int rank, int stars, int trophies) {
        String userNameId = account.getUsername();

        Bitmap drawing = drawings[getIndexForUserName(userNameId)];

        if (drawing != null) {
            GameResult gameResult = new GameResult(names, rank, stars, trophies, drawing);
            LocalDbForGameResults localDb =
                    new LocalDbHandlerForGameResults(this.getActivity(), null, 1);
            localDb.addGameResultToDb(gameResult);
        }
    }

    private void setFinishedCollectingRanking() {
        FbDatabase.setValueToUserInRoomAttribute(roomId, account.getUsername(), FINISHED, 1);
    }

    private class RankingAdapter extends ArrayAdapter<String> {

        private final String[] players;
        private final Integer[] rankings;
        private final String[] trophies;
        private final Bitmap[] drawings;
        private final Integer[] positions;

        private RankingAdapter(Context context, String[] players, Integer[] rankings,
                               Integer[] trophies, Bitmap[] drawings, Integer[] positions) {
            super(context, 0, players);
            this.players = players;
            this.rankings = rankings;
            this.trophies = RankingUtils.addSignToNumberList(trophies);
            this.drawings = drawings;
            this.positions = positions;
        }

        private void setTextToViews(int position, View convertView) {
            ((TextView) convertView.findViewById(R.id.playerName))
                    .setText(String.format("%d. %s", positions[position], players[position]));
            ((TextView) convertView.findViewById(R.id.trophiesWon))
                    .setText(trophies[position]);
            ((TextView) convertView.findViewById(R.id.starsWon))
                    .setText(RankingUtils.addSignToNumber(Math.max(rankings[position], 0)));
        }

        private void setHighlightColors(View convertView) {
            int yellowColor = getResources().getColor(R.color.colorDrawYellow);
            int greyColor = getResources().getColor(R.color.colorGrey);

            ((TextView) convertView.findViewById(R.id.playerName)).setTextColor(yellowColor);
            ((TextView) convertView.findViewById(R.id.trophiesWon)).setTextColor(yellowColor);
            ((TextView) convertView.findViewById(R.id.starsWon)).setTextColor(yellowColor);
            convertView.setBackgroundColor(greyColor);
        }

        private void setTypeFace(Typeface typeface, View... views) {
            for (View view : views) {
                ((TextView) view).setTypeface(typeface);
            }
        }

        @NonNull
        @Override
        public View getView(int position, View convertView, @NonNull ViewGroup parent) {

            // Check if an existing view is being reused, otherwise inflate the view
            convertView = LayoutInflater.from(getContext())
                    .inflate(R.layout.ranking_item, parent, false);

            setTypeFace(TypefaceLibrary.getTypeMuro(), convertView.findViewById(R.id.playerName),
                    convertView.findViewById(R.id.starsWon),
                    convertView.findViewById(R.id.trophiesWon),
                    convertView.findViewById(R.id.disconnectedRanking));

            // Update image
            ImageView drawingView = convertView.findViewById(R.id.drawing);
            TextView disconnectedTextView = convertView.findViewById(R.id.disconnectedRanking);
            if (rankings[position] >= 0) {
                disconnectedTextView.setVisibility(View.GONE);
                drawingView.setVisibility(View.VISIBLE);
                drawingView.setImageBitmap(drawings[getIndexForUserName(players[position])]);
            } else {
                disconnectedTextView.setVisibility(View.VISIBLE);
                drawingView.setVisibility(View.GONE);
            }

            // Set the color
            if (!players[position].equals(account.getUsername())) {
                setHighlightColors(convertView);
            }

            setTextToViews(position, convertView);

            // Return the completed view to render on screen
            return convertView;
        }
    }

    private void setHomeButtonListener() {
        activity.findViewById(R.id.homeButton).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        pressButton(view, LayoutUtils.AnimMode.CENTER, activity);
                        break;
                    case MotionEvent.ACTION_UP:
                        bounceButton(view, activity);
                        if (isPointInsideView(event.getRawX(), event.getRawY(), view)) {
                            activity.startHomeActivity();
                        }
                        break;
                    default:
                }
                return true;
            }
        });
    }
}