From b03704c97191d0dfe720e0907d40a5742b28d75d Mon Sep 17 00:00:00 2001 From: Fangh Date: Thu, 1 Feb 2024 22:38:34 +0100 Subject: [PATCH] feat: voting time is reduced if everyone has voted + pictures of a room are deleted at the end --- Assets/Scenes/ComputerView.unity | 185 +++++++++++++++++----- Assets/Scripts/DatabaseClasses/Room.cs | 20 +++ Assets/Scripts/RoomManager.cs | 108 +++++++------ Assets/Scripts/ScoringPage.cs | 8 + Assets/Scripts/StorageManager.cs | 80 +++++++++- Assets/Scripts/VotingPage.cs | 205 +++++++++++++++++-------- 6 files changed, 451 insertions(+), 155 deletions(-) diff --git a/Assets/Scenes/ComputerView.unity b/Assets/Scenes/ComputerView.unity index c72a832..d687847 100644 --- a/Assets/Scenes/ComputerView.unity +++ b/Assets/Scenes/ComputerView.unity @@ -1601,7 +1601,6 @@ GameObject: - component: {fileID: 351375052} - component: {fileID: 351375055} - component: {fileID: 351375054} - - component: {fileID: 351375053} m_Layer: 5 m_Name: Title2 m_TagString: Untagged @@ -1629,19 +1628,6 @@ RectTransform: m_AnchoredPosition: {x: 0, y: -50} m_SizeDelta: {x: 0, y: 320.82227} m_Pivot: {x: 0.5, y: 1} ---- !u!114 &351375053 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 351375051} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 94922ac68f10744df9dab89b5202ac76, type: 3} - m_Name: - m_EditorClassIdentifier: - textList: {fileID: 11400000, guid: 5b22791c486a626428ab508347ebb36e, type: 2} --- !u!114 &351375054 MonoBehaviour: m_ObjectHideFlags: 0 @@ -1865,6 +1851,7 @@ GameObject: - component: {fileID: 375256412} - component: {fileID: 375256415} - component: {fileID: 375256416} + - component: {fileID: 375256417} m_Layer: 0 m_Name: '[Managers]' m_TagString: Untagged @@ -1976,6 +1963,19 @@ MonoBehaviour: k__BackingField: k__BackingField: k__BackingField: +--- !u!114 &375256417 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 375256411} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b41deef4ebd372d5a18eabdb00cfbb4, type: 3} + m_Name: + m_EditorClassIdentifier: + cameraManager: {fileID: 0} --- !u!1 &411140634 GameObject: m_ObjectHideFlags: 0 @@ -2291,8 +2291,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 0} - m_AnchoredPosition: {x: 0, y: 40} - m_SizeDelta: {x: -80.00009, y: 642.6719} + m_AnchoredPosition: {x: 92.49994, y: 40} + m_SizeDelta: {x: -265.00012, y: 642.6719} m_Pivot: {x: 0.5, y: 0} --- !u!114 &496891793 MonoBehaviour: @@ -2311,7 +2311,7 @@ MonoBehaviour: m_Right: 0 m_Top: 0 m_Bottom: 0 - m_ChildAlignment: 5 + m_ChildAlignment: 3 m_StartCorner: 0 m_StartAxis: 0 m_CellSize: {x: 300, y: 200} @@ -2520,6 +2520,15 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: ae520d9a7647819498ae6228ced27630, type: 3} m_Name: m_EditorClassIdentifier: + playerStickers: + - {fileID: 1230545932} + - {fileID: 2120840640} + - {fileID: 1721928059} + - {fileID: 1602600781} + - {fileID: 2038769041} + - {fileID: 1059129458} + - {fileID: 1610615897} + - {fileID: 2004328314} --- !u!1 &593191224 GameObject: m_ObjectHideFlags: 0 @@ -3507,7 +3516,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.x - value: 1239.9999 + value: 1050 objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.y @@ -3529,6 +3538,10 @@ PrefabInstance: propertyPath: m_Name value: PlayerSticker (6) objectReference: {fileID: 0} + - target: {fileID: 4312846972391547553, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: @@ -3862,7 +3875,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.x - value: 1689.9999 + value: 1500 objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.y @@ -3884,6 +3897,10 @@ PrefabInstance: propertyPath: m_Name value: PlayerSticker (3) objectReference: {fileID: 0} + - target: {fileID: 4312846972391547553, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: @@ -4043,7 +4060,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.x - value: 339.99988 + value: 150 objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.y @@ -4672,7 +4689,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.x - value: 789.9999 + value: 600 objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.y @@ -4694,6 +4711,10 @@ PrefabInstance: propertyPath: m_Name value: PlayerSticker (5) objectReference: {fileID: 0} + - target: {fileID: 4312846972391547553, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: @@ -4707,6 +4728,17 @@ RectTransform: m_CorrespondingSourceObject: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} m_PrefabInstance: {fileID: 1059129456} m_PrefabAsset: {fileID: 0} +--- !u!114 &1059129458 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 9117562908589005100, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + m_PrefabInstance: {fileID: 1059129456} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 63ba002d2116d4c54a8d55e905869d8f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1001 &1097420890 PrefabInstance: m_ObjectHideFlags: 0 @@ -5402,6 +5434,17 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1197279070} m_CullTransparentMesh: 0 +--- !u!114 &1230545932 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 9117562908589005100, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + m_PrefabInstance: {fileID: 943114024} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 63ba002d2116d4c54a8d55e905869d8f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &1236996026 GameObject: m_ObjectHideFlags: 0 @@ -7504,7 +7547,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.x - value: 1239.9999 + value: 1050 objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.y @@ -7526,6 +7569,10 @@ PrefabInstance: propertyPath: m_Name value: PlayerSticker (2) objectReference: {fileID: 0} + - target: {fileID: 4312846972391547553, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: @@ -7539,6 +7586,28 @@ RectTransform: m_CorrespondingSourceObject: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} m_PrefabInstance: {fileID: 1595592696} m_PrefabAsset: {fileID: 0} +--- !u!114 &1602600781 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 9117562908589005100, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + m_PrefabInstance: {fileID: 851638680} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 63ba002d2116d4c54a8d55e905869d8f, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &1610615897 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 9117562908589005100, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + m_PrefabInstance: {fileID: 710475181} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 63ba002d2116d4c54a8d55e905869d8f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &1660260833 GameObject: m_ObjectHideFlags: 0 @@ -7868,6 +7937,17 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1681333512} m_CullTransparentMesh: 1 +--- !u!114 &1721928059 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 9117562908589005100, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + m_PrefabInstance: {fileID: 1595592696} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 63ba002d2116d4c54a8d55e905869d8f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &1730465902 GameObject: m_ObjectHideFlags: 0 @@ -8136,7 +8216,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.x - value: 789.9999 + value: 600 objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.y @@ -9778,7 +9858,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.x - value: 1689.9999 + value: 1500 objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.y @@ -9800,6 +9880,10 @@ PrefabInstance: propertyPath: m_Name value: PlayerSticker (7) objectReference: {fileID: 0} + - target: {fileID: 4312846972391547553, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: @@ -9813,6 +9897,17 @@ RectTransform: m_CorrespondingSourceObject: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} m_PrefabInstance: {fileID: 2004328312} m_PrefabAsset: {fileID: 0} +--- !u!114 &2004328314 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 9117562908589005100, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + m_PrefabInstance: {fileID: 2004328312} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 63ba002d2116d4c54a8d55e905869d8f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &2038490649 GameObject: m_ObjectHideFlags: 0 @@ -9959,7 +10054,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.x - value: 339.99988 + value: 150 objectReference: {fileID: 0} - target: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} propertyPath: m_AnchoredPosition.y @@ -9981,6 +10076,10 @@ PrefabInstance: propertyPath: m_Name value: PlayerSticker (4) objectReference: {fileID: 0} + - target: {fileID: 4312846972391547553, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: @@ -9994,6 +10093,17 @@ RectTransform: m_CorrespondingSourceObject: {fileID: 943229596838791819, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} m_PrefabInstance: {fileID: 2038769039} m_PrefabAsset: {fileID: 0} +--- !u!114 &2038769041 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 9117562908589005100, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + m_PrefabInstance: {fileID: 2038769039} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 63ba002d2116d4c54a8d55e905869d8f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &2065109612 GameObject: m_ObjectHideFlags: 0 @@ -10214,7 +10324,6 @@ GameObject: - component: {fileID: 2088869501} - component: {fileID: 2088869504} - component: {fileID: 2088869503} - - component: {fileID: 2088869502} m_Layer: 5 m_Name: QuestionMark m_TagString: Untagged @@ -10241,19 +10350,6 @@ RectTransform: m_AnchoredPosition: {x: -364, y: -228} m_SizeDelta: {x: 100, y: 100} m_Pivot: {x: 1, y: 0.5} ---- !u!114 &2088869502 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2088869500} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 94922ac68f10744df9dab89b5202ac76, type: 3} - m_Name: - m_EditorClassIdentifier: - textList: {fileID: 11400000, guid: 5b22791c486a626428ab508347ebb36e, type: 2} --- !u!114 &2088869503 MonoBehaviour: m_ObjectHideFlags: 0 @@ -10351,6 +10447,17 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2088869500} m_CullTransparentMesh: 1 +--- !u!114 &2120840640 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 9117562908589005100, guid: 69942fa558cf34dfc91982c6bccef840, type: 3} + m_PrefabInstance: {fileID: 1758412515} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 63ba002d2116d4c54a8d55e905869d8f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1001 &2214187228236614840 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/DatabaseClasses/Room.cs b/Assets/Scripts/DatabaseClasses/Room.cs index dfe1213..8637050 100644 --- a/Assets/Scripts/DatabaseClasses/Room.cs +++ b/Assets/Scripts/DatabaseClasses/Room.cs @@ -99,6 +99,26 @@ public List GetPropositionsForPlayer(Player player) return playerPropositions; } + + /// + /// Return the number of voters for a specific question + /// + /// + /// + public int NumbersOfVotersForQuestion(Question _question) + { + int numberOfVoters = 0; + + foreach(Proposition proposition in _question.propositions.Values.ToList()) + { + if (proposition.voters == null) + continue; + + numberOfVoters += proposition.voters.Count; + } + + return numberOfVoters; + } } public class ArrayToDictionaryConverter : JsonConverter> diff --git a/Assets/Scripts/RoomManager.cs b/Assets/Scripts/RoomManager.cs index d3ec59a..11f476a 100644 --- a/Assets/Scripts/RoomManager.cs +++ b/Assets/Scripts/RoomManager.cs @@ -10,9 +10,13 @@ using Firebase.Storage; using System.Security.Policy; using System.Threading.Tasks; +using System.Collections; +using System.Security.Cryptography; public class RoomManager : MonoBehaviour { + public static RoomManager Instance; + [Header("Waiting For Players Page")] public GameObject waitingForPlayersPage; /// @@ -40,12 +44,14 @@ public class RoomManager : MonoBehaviour [Header("Other")] public PromptList promptList; - private Room myRoom = null; + + public Room myRoom { get; private set; } = null; DatabaseReference realtimeDB; private void Awake() { + Instance = this; FirebaseInitializer.Instance.onFirebaseReady += Initialize; } @@ -92,16 +98,32 @@ private void ResetAllPlayerLabels() } } - private void OnApplicationQuit() + private bool deleteRoomFilesCompleted = false; + private bool deleteRealtimeDBCompleted = false; + + private IEnumerator OnApplicationQuit() { + Debug.Log($"delete files of room {myRoom.code} from storage", this); + StorageManager.Instance.DeleteFileOfRoom(myRoom, () => + { + Debug.Log($"cleaning photo files of room({myRoom.code})finish", this); + deleteRoomFilesCompleted = true; + }); + Debug.Log($"delete realtimeDB room {myRoom.code}"); realtimeDB.Child("rooms").Child(myRoom.code).RemoveValueAsync().ContinueWithOnMainThread(task => { - Debug.Log($"room {myRoom.code} has been deleted"); + Debug.Log($"room's({myRoom.code}) data has been deleted for database", this); myRoom = null; + deleteRealtimeDBCompleted = true; }); - Debug.Log($"delete files of room {myRoom.code}"); - DeleteRoomFiles(); + + while (!deleteRoomFilesCompleted || !deleteRealtimeDBCompleted) + { + yield return null; // Yield until both tasks are completed + } + + Debug.Log("Everything is clean. You can go. Bye bye..."); } private void Initialize() @@ -336,8 +358,25 @@ private void QueryRoomsInDatabase(Action> callback) { string JSON = snapshot.GetRawJsonValue(); Debug.Log($"Found some rooms:\n{JSON}", this); - Dictionary onlineRooms = JsonConvert.DeserializeObject>(JSON); - callback?.Invoke(onlineRooms.Values.ToList()); + try + { + Dictionary onlineRooms = JsonConvert.DeserializeObject>(JSON); + callback?.Invoke(onlineRooms.Values.ToList()); + } + catch (Exception e) + { + Debug.LogException(e); + Debug.LogError($"Room {JSON} was broken, deleting it", this); + snapshot.Reference.RemoveValueAsync().ContinueWithOnMainThread(task => + { + if (task.IsFaulted) + { + Debug.LogException(task.Exception); + return; + } + Debug.Log($"Broken room has been deleted", this); + }); ; + } } else { @@ -358,20 +397,27 @@ private void CleanOldRooms() { if (DateTime.FromOADate(r.creationDate) < oneHourLater) { - Debug.Log($"Room {r.code} has been created at {DateTime.FromOADate(r.creationDate)} and it's more than one hour old. Deleting it"); - realtimeDB.Child("rooms").Child(r.code).RemoveValueAsync().ContinueWithOnMainThread(task => - { - if (task.IsFaulted) - { - Debug.LogException(task.Exception); - return; - } - Debug.Log($"Room {r.code} has been deleted"); - }); + Debug.Log($"Room {r.code} has been created at {DateTime.FromOADate(r.creationDate)} and it's more than one hour old."); + DeleteRoom(r.code); } } }); } + + + private void DeleteRoom(string _roomCode) + { + realtimeDB.Child("rooms").Child(_roomCode).RemoveValueAsync().ContinueWithOnMainThread(task => + { + if (task.IsFaulted) + { + Debug.LogException(task.Exception); + return; + } + Debug.Log($"Room {_roomCode} has been deleted"); + }); + } + private async Task DoesPathExistAsync(StorageReference storageReference) { try @@ -392,32 +438,4 @@ private async Task DoesPathExistAsync(StorageReference storageReference) } } } - - private async void DeleteRoomFiles() - { - string roomCode = myRoom.code; //save it in case room has been deleted during you check files - - StorageReference roomFolder = FirebaseStorage.DefaultInstance.RootReference.Child(roomCode); - - bool pathExists = await DoesPathExistAsync(roomFolder); - - if (pathExists) - { - _ = roomFolder.DeleteAsync().ContinueWithOnMainThread(task => - { - if (task.IsCanceled || task.IsFaulted) - { - Debug.LogException(task.Exception); - } - else - { - Debug.Log($"Files of Room {roomCode} have been deleted"); - } - }); - } - else - { - Debug.Log($"Path for Room {roomCode} does not exist, nothing to delete"); - } - } } diff --git a/Assets/Scripts/ScoringPage.cs b/Assets/Scripts/ScoringPage.cs index 957d538..30917b2 100644 --- a/Assets/Scripts/ScoringPage.cs +++ b/Assets/Scripts/ScoringPage.cs @@ -6,6 +6,14 @@ public class ScoringPage : MonoBehaviour { [SerializeField] private List playerStickers; + private void Awake() + { + if(playerStickers == null || playerStickers.Count == 0) + { + Debug.LogError("You must provide the player stickers to the Scoring Page", this); + } + } + public void Initialize(Room _room) { gameObject.SetActive(true); diff --git a/Assets/Scripts/StorageManager.cs b/Assets/Scripts/StorageManager.cs index 9896c89..31711bc 100644 --- a/Assets/Scripts/StorageManager.cs +++ b/Assets/Scripts/StorageManager.cs @@ -3,6 +3,9 @@ using Firebase.Storage; using System; using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Security.Policy; using System.Threading.Tasks; using UnityEditor; @@ -11,12 +14,15 @@ public class StorageManager : MonoBehaviour { + public static StorageManager Instance; + public CameraManager cameraManager; private StorageReference storage; private DatabaseReference realtimeDB; void Awake() { + Instance = this; FirebaseInitializer.Instance.onFirebaseReady += Initialize; } @@ -27,18 +33,84 @@ void Initialize() realtimeDB = FirebaseDatabase.DefaultInstance.RootReference; } - // Start is called before the first frame update - void Start() + public void DeleteFileOfRoom(Room _room, Action callBack_OnFinish) { + List deleteTasks = new List(); + foreach(Player player in _room.players.Values.ToList()) + { + foreach(Proposition proposition in _room.GetPropositionsForPlayer(player)) + { + if (proposition != null) + { + if(proposition.photoUrl != null) + { + Debug.Log($"Adding a task to delete {proposition.photoUrl}", this); + deleteTasks.Add(Task.Run(async () => + { + string temp = proposition.photoUrl; + StorageReference imageRef = FirebaseStorage.DefaultInstance.GetReferenceFromUrl(temp); + Debug.Log($"deleting {temp}", this); + await imageRef.DeleteAsync(); + })); + } + } + } + } + if(deleteTasks.Count > 0) + { + RunDeleteTasks(deleteTasks, callBack_OnFinish); + } + else + { + Debug.Log($"There is no files to delete for room {_room.code}", this); + callBack_OnFinish.Invoke(); + } } - // Update is called once per frame - void Update() + private void RunDeleteTasks(List deleteTasks, Action callback_OnFinish) { + int taskCount = deleteTasks.Count; + Debug.Log($"There are {taskCount} files to delete", this); + Task.WhenAll(deleteTasks).ContinueWith(_ => + { + Debug.Log($"all delete tasks are done", this); + callback_OnFinish?.Invoke(); + }); } + /* + private IEnumerator RunDeleteTasks(List deleteTasks, Action callback_OnFinish) + { + int taskCount = deleteTasks.Count; + Debug.Log($"There are {taskCount} files to delete", this); + foreach (Task task in deleteTasks) + { + task.ContinueWith((completedTask) => + { + // This code will be executed when the task is completed. + taskCount--; + }); + + // Start the task + task.Start(); + } + while (taskCount > 0) + { + yield return null; + } + callback_OnFinish?.Invoke(); + } + + private Task DeletePhoto(string _gsURL) + { + string temp = _gsURL; + StorageReference imageRef = FirebaseStorage.DefaultInstance.GetReferenceFromUrl(temp); + Debug.Log($"deleting {temp}", this); + return imageRef.DeleteAsync(); + }*/ + public void UploadPhoto(string roomCode, string playerId, int question, int proposition, Action callback_OnPhotoUploaded) { Texture2D photo = cameraManager.GetPhoto(); diff --git a/Assets/Scripts/VotingPage.cs b/Assets/Scripts/VotingPage.cs index 36f58ae..54a3e6a 100644 --- a/Assets/Scripts/VotingPage.cs +++ b/Assets/Scripts/VotingPage.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using Firebase.Database; @@ -24,44 +23,77 @@ public class VotingPage : MonoBehaviour private Question currentQuestion = null; private DatabaseReference roomRef; - private Dictionary currentPlayers; //all the current playing players + private Dictionary currentPlayers; // All the current playing players private DateTime endOfTimer = DateTime.MinValue; private Action OnVoteEnded; + private bool allPlayersHaveVotedForCurrentQuestion = false; + + /// + /// Is the number of questions for this game sessions + /// + private int numberOfQuestions = 0; private void Update() { - //there is no question displayed or timer is not started + // If there is no question displayed or the timer is not started, return early. if (currentQuestion == null || endOfTimer == DateTime.MinValue) return; - if (DateTime.Now < endOfTimer) { TimeSpan duration = endOfTimer - DateTime.Now; timerLabel.text = ((int)duration.TotalSeconds).ToString("D2"); + + if (allPlayersHaveVotedForCurrentQuestion) + { + Debug.Log("All players have voted. So I put only 5sec to look at the winner.", this); + if(endOfTimer > DateTime.Now.AddSeconds(5)) + { + endOfTimer = DateTime.Now.AddSeconds(5); + } + } } else { - timerLabel.text = "0"; - if (remainingQuestions.Count > 0) + EndCurrentQuestion(); + } + } + + /// + /// End current question and timer and go to next question (or end the vote if there is no more questions) + /// + private void EndCurrentQuestion() + { + timerLabel.text = "0"; + if (remainingQuestions.Count > 0) + { + currentQuestion = remainingQuestions.Dequeue(); + ShowNextQuestion(); + } + else + { + OnVoteEnded?.Invoke(); + OnVoteEnded = null; + gameObject.SetActive(false); + + for (int i = 0; i < numberOfQuestions; i++) { - currentQuestion = remainingQuestions.Dequeue(); - ShowQuestion(); - } - else - { - OnVoteEnded?.Invoke(); - OnVoteEnded = null; - gameObject.SetActive(false); + roomRef.Child("questions").Child(i.ToString()).ValueChanged -= OnQuestionDataUpdate; } } } - - // Start is called before the first frame update + /// + /// Initializes the voting page with necessary data, such as the room reference, current players, + /// questions, and a callback function for when the voting ends. + /// + /// Reference to the Firebase room database. + /// Dictionary of current players. + /// Dictionary of questions associated with their IDs. + /// Callback function to invoke when the voting ends. public void ShowVotingPage(DatabaseReference _roomRef, Dictionary _currentPlayers, Dictionary _questions, Action _callback_OnVoteEnded) { Debug.Log("Initializing voting page"); @@ -71,99 +103,138 @@ public void ShowVotingPage(DatabaseReference _roomRef, Dictionary - /// Display next question on screen + /// Displays the next question on the screen, updating the prompt, timer, and proposition frames. /// - void ShowQuestion() + private void ShowNextQuestion() { + // Set the current question ID in the Firebase room database. roomRef.Child("currentQuestionId").SetValueAsync(currentQuestion.index); + // Update the prompt text based on the current question's prompt ID. Debug.Log($"Show Question {currentQuestion.promptId}", this); Prompt currentPrompt = promptList.GetPromptById(currentQuestion.promptId); currentPromptLabel.text = currentPrompt.en; Debug.Log($"Prompt is {currentPromptLabel.text}", this); - if (currentQuestion.propositions[0] != null) - proposition1.Initialize(currentQuestion.propositions[0]); - else - { - Debug.Log("User has given no proposition", this); - //manage if there is no proposition - } - - if (currentQuestion.propositions[1] != null) - proposition2.Initialize(currentQuestion.propositions[1]); - else - { - Debug.Log("User has given no proposition", this); - //manage if there is no proposition - } + // Initialize the proposition frames with proposition data. + InitializeProposition(proposition1, currentQuestion.propositions[0]); + InitializeProposition(proposition2, currentQuestion.propositions[1]); + // Set the timer to end after the specified voting time. endOfTimer = DateTime.Now.AddSeconds(votingTime); + + //reset the count of voters + allPlayersHaveVotedForCurrentQuestion = false; } /// - /// Is called when a question is updated (someone has voted) + /// Initializes a proposition frame with the provided proposition data, updating it if available, + /// or handling the case when there is no proposition. /// - /// - /// - private void OnQuestionChanged(object sender, ValueChangedEventArgs _questionRef) + /// The PropositionFrame to initialize or update. + /// The Proposition data to use for initialization or update. + private void InitializeProposition(PropositionFrame proposition, Proposition propositionData) + { + if (propositionData != null) + { + proposition.Initialize(propositionData); + } + else + { + Debug.Log("User has given no proposition", this); + // Handle the case when there is no proposition + } + } + + /// + /// Handles updates to a question, such as when someone has voted for it. + /// + /// The sender of the event. + /// The ValueChangedEventArgs containing the updated question reference. + private void OnQuestionDataUpdate(object sender, ValueChangedEventArgs _questionRef) { - //Debug.Log("a question value has changed, maybe someone has voted", this); string JSON = _questionRef.Snapshot.GetRawJsonValue(); + + if (string.IsNullOrEmpty(JSON)) + return; + Question question = Newtonsoft.Json.JsonConvert.DeserializeObject(JSON); - //if someone succeeded to vote for another question than the one that is displayed => yeet + // If someone succeeded in voting for another question than the one displayed, ignore it. if (question.index != currentQuestion.index) return; - //Debug.Log($"someone has voted for {question.index}", this); currentQuestion.propositions = question.propositions; - UpdateVoters(); + + if (currentQuestion.propositions.Count > 0) + { + // Update the proposition voters for both propositions. + UpdatePropositionVoters(proposition1, currentQuestion.propositions[0]); + UpdatePropositionVoters(proposition2, currentQuestion.propositions[1]); + } + + if (RoomManager.Instance.myRoom.NumbersOfVotersForQuestion(currentQuestion) >= currentPlayers.Count) + { + allPlayersHaveVotedForCurrentQuestion = true; + } } - private void UpdateVoters() + /// + /// Updates the voters for a specific proposition frame based on the provided proposition data. + /// If the proposition data is not null, it retrieves the list of voters and updates the frame. + /// If there is no proposition data, it logs a message indicating that the user has not given a proposition. + /// + /// The PropositionFrame to update. + /// The Proposition data used to update voters for the proposition frame. + private void UpdatePropositionVoters(PropositionFrame proposition, Proposition propositionData) { - if (currentQuestion.propositions.Count == 0) //manage if there is no propositons - return; - - if (currentQuestion.propositions[0] != null) + if (propositionData != null) { - List playersThatHasVotedForFirstProposition = new List(); - if (currentQuestion.propositions[0].voters != null) + List voters = GetVotersForProposition(propositionData); + proposition.UpdateVoters(voters); + } + else + { + Debug.Log("User has given no proposition", this); + // Handle the case when there is no proposition + } + } + + /// + /// Retrieves the list of players who have voted for a specific proposition based on the provided proposition data. + /// It checks if the proposition data contains a list of voters and then looks up player information in the current players dictionary. + /// + /// The Proposition data for which to retrieve voters. + /// The list of players who voted for the proposition. + private List GetVotersForProposition(Proposition propositionData) + { + List voters = new List(); + + if (propositionData.voters != null) + { + foreach (string playerId in propositionData.voters) { - foreach (string playerId in currentQuestion.propositions[0].voters) - { - playersThatHasVotedForFirstProposition.Add(currentPlayers[playerId]); - } - proposition1.UpdateVoters(playersThatHasVotedForFirstProposition); + voters.Add(currentPlayers[playerId]); + Debug.Log($"updating number of voters for: {propositionData.owner.name}'s propositions. They are now {voters.Count}."); } } - if (currentQuestion.propositions[1] != null) - { - List playersThatHasVotedForSecondProposition = new List(); - if (currentQuestion.propositions[1].voters != null) - { - foreach (string playerId in currentQuestion.propositions[1].voters) - { - playersThatHasVotedForSecondProposition.Add(currentPlayers[playerId]); - } - proposition2.UpdateVoters(playersThatHasVotedForSecondProposition); - } - } + return voters; } } +