Skip to content

Commit

Permalink
Merge pull request #37 from milospi/fix/realtimesync
Browse files Browse the repository at this point in the history
fix syncing
  • Loading branch information
mostafas authored Apr 10, 2026
2 parents b7b20c0 + f1b3c01 commit 78dbe24
Show file tree
Hide file tree
Showing 11 changed files with 694 additions and 123 deletions.
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

0 comments on commit 78dbe24

Please sign in to comment.