Skip to content

fix syncing #37

Merged
merged 1 commit into from
Apr 10, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package group07.beatbattle.android.firebase;

import java.util.List;

import group07.beatbattle.firebase.FirebaseGateway;

public class AndroidFirebaseGateway implements FirebaseGateway {
Expand All @@ -24,14 +26,7 @@ public void createSession(
int totalRounds,
CreateSessionCallback callback
) {
sessionRepository.createSession(
gamePin,
hostId,
state,
currentRound,
totalRounds,
callback
);
sessionRepository.createSession(gamePin, hostId, state, currentRound, totalRounds, callback);
}

@Override
Expand Down Expand Up @@ -64,6 +59,11 @@ public void listenToPlayers(String sessionId, PlayersListenerCallback callback)
sessionRepository.listenToPlayers(sessionId, callback);
}

@Override
public void fetchPlayers(String sessionId, PlayersListenerCallback callback) {
sessionRepository.fetchPlayers(sessionId, callback);
}

@Override
public void removePlayerFromSession(
String sessionId,
Expand All @@ -74,10 +74,32 @@ public void removePlayerFromSession(
}

@Override
public void deleteSession(
String sessionId,
DeleteSessionCallback callback
) {
public void deleteSession(String sessionId, DeleteSessionCallback callback) {
sessionRepository.deleteSession(sessionId, callback);
}

@Override
public void storeQuestions(String sessionId, List<QuestionData> questions, SimpleCallback callback) {
sessionRepository.storeQuestions(sessionId, questions, callback);
}

@Override
public void getQuestions(String sessionId, GetQuestionsCallback callback) {
sessionRepository.getQuestions(sessionId, callback);
}

@Override
public void updateSessionState(String sessionId, String state, SimpleCallback callback) {
sessionRepository.updateSessionState(sessionId, state, callback);
}

@Override
public void listenToSessionState(String sessionId, SessionStateListener listener) {
sessionRepository.listenToSessionState(sessionId, listener);
}

@Override
public void updatePlayerScore(String sessionId, String playerId, int score, SimpleCallback callback) {
sessionRepository.updatePlayerScore(sessionId, playerId, score, callback);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package group07.beatbattle.android.firebase;

import com.google.firebase.Timestamp;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.ListenerRegistration;
import com.google.firebase.firestore.QuerySnapshot;
import com.google.firebase.firestore.WriteBatch;

import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -17,6 +20,7 @@ public class FirestoreSessionRepository {

private static final String SESSIONS = "Sessions";
private static final String PLAYERS = "Players";
private static final String QUESTIONS = "Questions";

private final FirebaseFirestore firestore;

Expand Down Expand Up @@ -162,6 +166,31 @@ public ListenerRegistration listenToPlayers(
});
}

public void fetchPlayers(
String sessionId,
FirebaseGateway.PlayersListenerCallback callback
) {
firestore.collection(SESSIONS)
.document(sessionId)
.collection(PLAYERS)
.get()
.addOnSuccessListener(snapshot -> {
List<Player> players = new ArrayList<>();
for (DocumentSnapshot document : snapshot.getDocuments()) {
String playerId = document.getId();
String name = document.getString("name");
if (name == null) name = "Unknown";
boolean isHost = Boolean.TRUE.equals(document.getBoolean("isHost"));
Player player = new Player(playerId, name, isHost);
Long scoreValue = document.getLong("score");
if (scoreValue != null) player.setScore(scoreValue.intValue());
players.add(player);
}
callback.onPlayersChanged(players);
})
.addOnFailureListener(callback::onFailure);
}

public void removePlayerFromSession(
String sessionId,
String playerId,
Expand Down Expand Up @@ -229,4 +258,114 @@ private void deleteSessionDocument(
.addOnSuccessListener(unused -> callback.onSuccess())
.addOnFailureListener(callback::onFailure);
}

public void storeQuestions(
String sessionId,
List<FirebaseGateway.QuestionData> questions,
FirebaseGateway.SimpleCallback callback
) {
WriteBatch batch = firestore.batch();
CollectionReference questionsRef = firestore
.collection(SESSIONS)
.document(sessionId)
.collection(QUESTIONS);

for (FirebaseGateway.QuestionData q : questions) {
Map<String, Object> data = new HashMap<>();
data.put("songId", q.songId);
data.put("songTitle", q.songTitle);
data.put("songArtist", q.songArtist);
data.put("previewUrl", q.previewUrl);
data.put("albumArtUrl", q.albumArtUrl != null ? q.albumArtUrl : "");
data.put("options", q.options);
data.put("roundIndex", q.roundIndex);
batch.set(questionsRef.document(String.valueOf(q.roundIndex)), data);
}

batch.commit()
.addOnSuccessListener(unused -> callback.onSuccess())
.addOnFailureListener(callback::onFailure);
}

public void getQuestions(
String sessionId,
FirebaseGateway.GetQuestionsCallback callback
) {
firestore.collection(SESSIONS)
.document(sessionId)
.collection(QUESTIONS)
.orderBy("roundIndex")
.get()
.addOnSuccessListener(snapshot -> {
List<FirebaseGateway.QuestionData> questions = new ArrayList<>();
for (DocumentSnapshot doc : snapshot.getDocuments()) {
String songId = doc.getString("songId");
String songTitle = doc.getString("songTitle");
String songArtist = doc.getString("songArtist");
String previewUrl = doc.getString("previewUrl");
String albumArtUrl = doc.getString("albumArtUrl");
List<String> options = (List<String>) doc.get("options");
Long roundIndexLong = doc.getLong("roundIndex");
int roundIndex = roundIndexLong != null ? roundIndexLong.intValue() : 0;

questions.add(new FirebaseGateway.QuestionData(
songId, songTitle, songArtist, previewUrl, albumArtUrl, options, roundIndex
));
}
callback.onSuccess(questions);
})
.addOnFailureListener(callback::onFailure);
}

public void updateSessionState(
String sessionId,
String state,
FirebaseGateway.SimpleCallback callback
) {
Map<String, Object> update = new HashMap<>();
update.put("state", state);

firestore.collection(SESSIONS)
.document(sessionId)
.update(update)
.addOnSuccessListener(unused -> callback.onSuccess())
.addOnFailureListener(callback::onFailure);
}

public void listenToSessionState(
String sessionId,
FirebaseGateway.SessionStateListener listener
) {
firestore.collection(SESSIONS)
.document(sessionId)
.addSnapshotListener((snapshot, error) -> {
if (error != null) {
listener.onFailure(error);
return;
}
if (snapshot == null || !snapshot.exists()) return;
String state = snapshot.getString("state");
if (state != null) {
listener.onStateChanged(state);
}
});
}

public void updatePlayerScore(
String sessionId,
String playerId,
int score,
FirebaseGateway.SimpleCallback callback
) {
Map<String, Object> update = new HashMap<>();
update.put("score", score);

firestore.collection(SESSIONS)
.document(sessionId)
.collection(PLAYERS)
.document(playerId)
.update(update)
.addOnSuccessListener(unused -> callback.onSuccess())
.addOnFailureListener(callback::onFailure);
}
}
21 changes: 21 additions & 0 deletions core/src/main/java/group07/beatbattle/BeatBattle.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public BeatBattle(FirebaseGateway firebaseGateway) {
private MusicService musicService;
private AudioPlayer audioPlayer;

private String localPlayerId;
private String localPlayerName;
private String localSessionId;
private boolean localIsHost;

public void setServices(MusicService musicService, AudioPlayer audioPlayer) {
this.musicService = musicService;
this.audioPlayer = audioPlayer;
Expand All @@ -41,6 +46,22 @@ public void setServices(MusicService musicService, AudioPlayer audioPlayer) {
public MusicService getMusicService() { return musicService; }
public AudioPlayer getAudioPlayer() { return audioPlayer; }

public void setLocalPlayer(String id, String name) {
this.localPlayerId = id;
this.localPlayerName = name;
}

public String getLocalPlayerId() { return localPlayerId; }
public String getLocalPlayerName() { return localPlayerName; }

public void setLocalSession(String sessionId, boolean isHost) {
this.localSessionId = sessionId;
this.localIsHost = isHost;
}

public String getLocalSessionId() { return localSessionId; }
public boolean isLocalHost() { return localIsHost; }

@Override
public void create() {
montserratFont = loadFont("fonts/Montserrat-Regular.ttf", 54);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ public Leaderboard getLeaderboard() {
return leaderboard;
}

/** Returns the leaderboard entry for the local player (index 0), or null if session is empty. */
/** Returns the leaderboard entry for the local player, or null if not found. */
public LeaderboardEntry getLocalPlayerEntry() {
if (session.getPlayers().isEmpty()) return null;
String localId = session.getPlayers().get(0).getId();
String localId = game.getLocalPlayerId();
if (localId == null && !session.getPlayers().isEmpty()) {
localId = session.getPlayers().get(0).getId();
}
if (localId == null) return null;
for (LeaderboardEntry entry : leaderboard.getEntries()) {
if (entry.getPlayerId().equals(localId)) return entry;
}
Expand Down
Loading
Loading