< Summary

Class:EventsSubSectionComponentController
Assembly:ExploreV2
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/ExploreV2/Scripts/Sections/PlacesAndEventsSection/SubSections/EventsSubSection/EventsSubSectionMenu/EventsSubSectionComponentController.cs
Covered lines:135
Uncovered lines:36
Coverable lines:171
Total lines:388
Line coverage:78.9% (135 of 171)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
EventsSubSectionComponentController(...)0%110100%
FirstLoading()0%110100%
OnExploreV2Open(...)0%6200%
RequestAllEvents()0%22091.67%
RequestAllEventsFromAPI()0%220100%
OnRequestedEventsUpdated()0%110100%
LoadFeaturedEvents()0%440100%
LoadTrendingEvents()0%3.243070%
LoadUpcomingEvents()0%2.082072.73%
ShowMoreUpcomingEvents()0%5.795068.42%
LoadGoingEvents()0%3.243070%
Dispose()0%110100%
CreateEventCardModelFromAPIEvent(...)0%110100%
FormatEventDate(...)0%110100%
FormatEventStartDate(...)0%64050%
FormatEventStartDateFromTo(...)0%110100%
FormatEventOrganized(...)0%110100%
FormatEventPlace(...)0%220100%
ShowEventDetailedInfo(...)0%2.062075%
JumpInToEvent(...)0%5.015091.67%
SubscribeToEvent(...)0%6200%
UnsubscribeToEvent(...)0%6200%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/ExploreV2/Scripts/Sections/PlacesAndEventsSection/SubSections/EventsSubSection/EventsSubSectionMenu/EventsSubSectionComponentController.cs

#LineLine coverage
 1using DCL;
 2using DCL.Interface;
 3using ExploreV2Analytics;
 4using System;
 5using System.Collections.Generic;
 6using System.Globalization;
 7using System.Linq;
 8using UnityEngine;
 9
 10public interface IEventsSubSectionComponentController : IDisposable
 11{
 12    /// <summary>
 13    /// It will be triggered when the sub-section want to request to close the ExploreV2 main menu.
 14    /// </summary>
 15    event Action OnCloseExploreV2;
 16
 17    /// <summary>
 18    /// It will be triggered when any action is executed inside the events sub-section.
 19    /// </summary>
 20    event Action OnAnyActionExecuted;
 21
 22    /// <summary>
 23    /// Request all events from the API.
 24    /// </summary>
 25    void RequestAllEvents();
 26
 27    /// <summary>
 28    /// Load the featured events with the last requested ones.
 29    /// </summary>
 30    void LoadFeaturedEvents();
 31
 32    /// <summary>
 33    /// Load the trending events with the last requested ones.
 34    /// </summary>
 35    void LoadTrendingEvents();
 36
 37    /// <summary>
 38    /// Load the upcoming events with the last requested ones.
 39    /// </summary>
 40    void LoadUpcomingEvents();
 41
 42    /// <summary>
 43    /// Increment the number of upcoming events loaded.
 44    /// </summary>
 45    void ShowMoreUpcomingEvents();
 46
 47    /// <summary>
 48    /// Load the going events with the last requested ones.
 49    /// </summary>
 50    void LoadGoingEvents();
 51}
 52
 53public class EventsSubSectionComponentController : IEventsSubSectionComponentController
 54{
 55    public event Action OnCloseExploreV2;
 56    public event Action OnAnyActionExecuted;
 57    internal event Action OnEventsFromAPIUpdated;
 58
 59    internal const int DEFAULT_NUMBER_OF_FEATURED_EVENTS = 3;
 60    internal const int INITIAL_NUMBER_OF_UPCOMING_ROWS = 1;
 61    internal const int SHOW_MORE_UPCOMING_ROWS_INCREMENT = 1;
 62    internal const string LIVE_TAG_TEXT = "LIVE";
 63    internal const string EVENT_DETAIL_URL = "https://events.decentraland.org/event/?id={0}";
 64    internal IEventsSubSectionComponentView view;
 65    internal IEventsAPIController eventsAPIApiController;
 2066    internal List<EventFromAPIModel> eventsFromAPI = new List<EventFromAPIModel>();
 67    internal int currentUpcomingEventsShowed = 0;
 68    internal bool reloadEvents = false;
 69    internal IExploreV2Analytics exploreV2Analytics;
 70
 2071    public EventsSubSectionComponentController(IEventsSubSectionComponentView view, IEventsAPIController eventsAPI, IExp
 72    {
 2073        this.view = view;
 2074        this.view.OnReady += FirstLoading;
 2075        this.view.OnInfoClicked += ShowEventDetailedInfo;
 2076        this.view.OnJumpInClicked += JumpInToEvent;
 2077        this.view.OnSubscribeEventClicked += SubscribeToEvent;
 2078        this.view.OnUnsubscribeEventClicked += UnsubscribeToEvent;
 2079        this.view.OnShowMoreUpcomingEventsClicked += ShowMoreUpcomingEvents;
 80
 2081        eventsAPIApiController = eventsAPI;
 2082        OnEventsFromAPIUpdated += OnRequestedEventsUpdated;
 83
 2084        this.exploreV2Analytics = exploreV2Analytics;
 2085    }
 86
 87    internal void FirstLoading()
 88    {
 189        reloadEvents = true;
 190        RequestAllEvents();
 91
 192        view.OnEventsSubSectionEnable += RequestAllEvents;
 193        DataStore.i.exploreV2.isOpen.OnChange += OnExploreV2Open;
 194    }
 95
 96    internal void OnExploreV2Open(bool current, bool previous)
 97    {
 098        if (current)
 099            return;
 100
 0101        reloadEvents = true;
 0102    }
 103
 104    public void RequestAllEvents()
 105    {
 2106        if (!reloadEvents)
 0107            return;
 108
 2109        currentUpcomingEventsShowed = view.currentUpcomingEventsPerRow * INITIAL_NUMBER_OF_UPCOMING_ROWS;
 2110        view.RestartScrollViewPosition();
 2111        view.SetFeaturedEventsAsLoading(true);
 2112        view.SetTrendingEventsAsLoading(true);
 2113        view.SetUpcomingEventsAsLoading(true);
 2114        view.SetShowMoreUpcomingEventsButtonActive(false);
 2115        view.SetGoingEventsAsLoading(true);
 2116        RequestAllEventsFromAPI();
 2117        reloadEvents = false;
 2118    }
 119
 120    internal void RequestAllEventsFromAPI()
 121    {
 3122        eventsAPIApiController.GetAllEvents(
 123            (eventList) =>
 124            {
 0125                eventsFromAPI = eventList;
 0126                OnEventsFromAPIUpdated?.Invoke();
 0127            },
 128            (error) =>
 129            {
 0130                Debug.LogError($"Error receiving events from the API: {error}");
 0131            });
 3132    }
 133
 134    internal void OnRequestedEventsUpdated()
 135    {
 1136        LoadFeaturedEvents();
 1137        LoadTrendingEvents();
 1138        LoadUpcomingEvents();
 1139        LoadGoingEvents();
 1140    }
 141
 142    public void LoadFeaturedEvents()
 143    {
 2144        List<EventCardComponentModel> featuredEvents = new List<EventCardComponentModel>();
 6145        List<EventFromAPIModel> eventsFiltered = eventsFromAPI.Where(e => e.highlighted).ToList();
 146
 2147        if (eventsFiltered.Count == 0)
 2148            eventsFiltered = eventsFromAPI.Take(DEFAULT_NUMBER_OF_FEATURED_EVENTS).ToList();
 149
 12150        foreach (EventFromAPIModel receivedEvent in eventsFiltered)
 151        {
 4152            EventCardComponentModel eventCardModel = CreateEventCardModelFromAPIEvent(receivedEvent);
 4153            featuredEvents.Add(eventCardModel);
 154        }
 155
 2156        view.SetFeaturedEvents(featuredEvents);
 2157        view.SetFeaturedEventsAsLoading(false);
 2158        view.SetFeaturedEventsActive(featuredEvents.Count > 0);
 2159    }
 160
 161    public void LoadTrendingEvents()
 162    {
 2163        List<EventCardComponentModel> trendingEvents = new List<EventCardComponentModel>();
 6164        List<EventFromAPIModel> eventsFiltered = eventsFromAPI.Where(e => e.trending).ToList();
 165
 4166        foreach (EventFromAPIModel receivedEvent in eventsFiltered)
 167        {
 0168            EventCardComponentModel eventCardModel = CreateEventCardModelFromAPIEvent(receivedEvent);
 0169            trendingEvents.Add(eventCardModel);
 170        }
 171
 2172        view.SetTrendingEvents(trendingEvents);
 2173        view.SetTrendingEventsAsLoading(false);
 2174    }
 175
 176    public void LoadUpcomingEvents()
 177    {
 2178        List<EventCardComponentModel> upcomingEvents = new List<EventCardComponentModel>();
 2179        List<EventFromAPIModel> eventsFiltered = eventsFromAPI.Take(currentUpcomingEventsShowed).ToList();
 180
 4181        foreach (EventFromAPIModel receivedEvent in eventsFiltered)
 182        {
 0183            EventCardComponentModel eventCardModel = CreateEventCardModelFromAPIEvent(receivedEvent);
 0184            upcomingEvents.Add(eventCardModel);
 185        }
 186
 2187        view.SetUpcomingEvents(upcomingEvents);
 2188        view.SetShowMoreUpcomingEventsButtonActive(currentUpcomingEventsShowed < eventsFromAPI.Count);
 2189        view.SetUpcomingEventsAsLoading(false);
 2190    }
 191
 192    public void ShowMoreUpcomingEvents()
 193    {
 2194        List<EventCardComponentModel> upcomingEvents = new List<EventCardComponentModel>();
 2195        List<EventFromAPIModel> eventsFiltered = new List<EventFromAPIModel>();
 2196        int numberOfExtraItemsToAdd = ((int)Mathf.Ceil((float)currentUpcomingEventsShowed / view.currentUpcomingEventsPe
 2197        int numberOfItemsToAdd = view.currentUpcomingEventsPerRow * SHOW_MORE_UPCOMING_ROWS_INCREMENT + numberOfExtraIte
 198
 2199        if (currentUpcomingEventsShowed + numberOfItemsToAdd <= eventsFromAPI.Count)
 2200            eventsFiltered = eventsFromAPI.GetRange(currentUpcomingEventsShowed, numberOfItemsToAdd);
 201        else
 0202            eventsFiltered = eventsFromAPI.GetRange(currentUpcomingEventsShowed, eventsFromAPI.Count - currentUpcomingEv
 203
 4204        foreach (EventFromAPIModel receivedEvent in eventsFiltered)
 205        {
 0206            EventCardComponentModel placeCardModel = CreateEventCardModelFromAPIEvent(receivedEvent);
 0207            upcomingEvents.Add(placeCardModel);
 208        }
 209
 2210        view.AddUpcomingEvents(upcomingEvents);
 211
 2212        currentUpcomingEventsShowed += numberOfItemsToAdd;
 2213        if (currentUpcomingEventsShowed > eventsFromAPI.Count)
 0214            currentUpcomingEventsShowed = eventsFromAPI.Count;
 215
 2216        view.SetShowMoreUpcomingEventsButtonActive(currentUpcomingEventsShowed < eventsFromAPI.Count);
 217
 2218        OnAnyActionExecuted?.Invoke();
 0219    }
 220
 221    public void LoadGoingEvents()
 222    {
 2223        List<EventCardComponentModel> goingEvents = new List<EventCardComponentModel>();
 6224        List<EventFromAPIModel> eventsFiltered = eventsFromAPI.Where(e => e.attending).ToList();
 225
 4226        foreach (EventFromAPIModel receivedEvent in eventsFiltered)
 227        {
 0228            EventCardComponentModel eventCardModel = CreateEventCardModelFromAPIEvent(receivedEvent);
 0229            goingEvents.Add(eventCardModel);
 230        }
 231
 2232        view.SetGoingEvents(goingEvents);
 2233        view.SetGoingEventsAsLoading(false);
 2234    }
 235
 236    public void Dispose()
 237    {
 20238        view.OnReady -= FirstLoading;
 20239        view.OnInfoClicked -= ShowEventDetailedInfo;
 20240        view.OnJumpInClicked -= JumpInToEvent;
 20241        view.OnSubscribeEventClicked -= SubscribeToEvent;
 20242        view.OnUnsubscribeEventClicked -= UnsubscribeToEvent;
 20243        view.OnShowMoreUpcomingEventsClicked -= ShowMoreUpcomingEvents;
 20244        view.OnEventsSubSectionEnable -= RequestAllEvents;
 20245        OnEventsFromAPIUpdated -= OnRequestedEventsUpdated;
 20246        DataStore.i.exploreV2.isOpen.OnChange -= OnExploreV2Open;
 20247    }
 248
 249    internal EventCardComponentModel CreateEventCardModelFromAPIEvent(EventFromAPIModel eventFromAPI)
 250    {
 5251        EventCardComponentModel eventCardModel = new EventCardComponentModel();
 5252        eventCardModel.eventId = eventFromAPI.id;
 5253        eventCardModel.eventPictureUri = eventFromAPI.image;
 5254        eventCardModel.isLive = eventFromAPI.live;
 5255        eventCardModel.liveTagText = LIVE_TAG_TEXT;
 5256        eventCardModel.eventDateText = FormatEventDate(eventFromAPI);
 5257        eventCardModel.eventName = eventFromAPI.name;
 5258        eventCardModel.eventDescription = eventFromAPI.description;
 5259        eventCardModel.eventStartedIn = FormatEventStartDate(eventFromAPI);
 5260        eventCardModel.eventStartsInFromTo = FormatEventStartDateFromTo(eventFromAPI);
 5261        eventCardModel.eventOrganizer = FormatEventOrganized(eventFromAPI);
 5262        eventCardModel.eventPlace = FormatEventPlace(eventFromAPI);
 5263        eventCardModel.subscribedUsers = eventFromAPI.total_attendees;
 5264        eventCardModel.isSubscribed = false;
 5265        eventCardModel.coords = new Vector2Int(eventFromAPI.coordinates[0], eventFromAPI.coordinates[1]);
 5266        eventCardModel.eventFromAPIInfo = eventFromAPI;
 267
 268        // Card events
 5269        return eventCardModel;
 270    }
 271
 272    internal string FormatEventDate(EventFromAPIModel eventFromAPI)
 273    {
 6274        DateTime eventDateTime = Convert.ToDateTime(eventFromAPI.next_start_at).ToUniversalTime();
 6275        return eventDateTime.ToString("MMMM d", new CultureInfo("en-US"));
 276    }
 277
 278    internal string FormatEventStartDate(EventFromAPIModel eventFromAPI)
 279    {
 6280        DateTime eventDateTime = Convert.ToDateTime(eventFromAPI.next_start_at).ToUniversalTime();
 281        string formattedDate;
 6282        if (eventFromAPI.live)
 283        {
 6284            int daysAgo = (int)Math.Ceiling((DateTime.Now - eventDateTime).TotalDays);
 6285            int hoursAgo = (int)Math.Ceiling((DateTime.Now - eventDateTime).TotalHours);
 286
 6287            if (daysAgo > 0)
 6288                formattedDate = $"{daysAgo} days ago";
 289            else
 0290                formattedDate = $"{hoursAgo} hr ago";
 0291        }
 292        else
 293        {
 0294            int daysToStart = (int)Math.Ceiling((eventDateTime - DateTime.Now).TotalDays);
 0295            int hoursToStart = (int)Math.Ceiling((eventDateTime - DateTime.Now).TotalHours);
 296
 0297            if (daysToStart > 0)
 0298                formattedDate = $"in {daysToStart} days";
 299            else
 0300                formattedDate = $"in {hoursToStart} hours";
 301        }
 302
 6303        return formattedDate;
 304    }
 305
 306    internal string FormatEventStartDateFromTo(EventFromAPIModel eventFromAPI)
 307    {
 6308        CultureInfo cultureInfo = new CultureInfo("en-US");
 6309        DateTime eventStartDateTime = Convert.ToDateTime(eventFromAPI.next_start_at).ToUniversalTime();
 6310        DateTime eventEndDateTime = Convert.ToDateTime(eventFromAPI.finish_at).ToUniversalTime();
 6311        string formattedDate = $"From {eventStartDateTime.ToString("dddd", cultureInfo)}, {eventStartDateTime.Day} {even
 312                               $" to {eventEndDateTime.ToString("dddd", cultureInfo)}, {eventEndDateTime.Day} {eventEndD
 313
 6314        return formattedDate;
 315    }
 316
 6317    internal string FormatEventOrganized(EventFromAPIModel eventFromAPI) { return $"Public, Organized by {eventFromAPI.u
 318
 6319    internal string FormatEventPlace(EventFromAPIModel eventFromAPI) { return string.IsNullOrEmpty(eventFromAPI.scene_na
 320
 321    internal void ShowEventDetailedInfo(EventCardComponentModel eventModel)
 322    {
 1323        view.ShowEventModal(eventModel);
 1324        exploreV2Analytics.SendClickOnEventInfo(eventModel.eventId, eventModel.eventName);
 1325        OnAnyActionExecuted?.Invoke();
 0326    }
 327
 328    internal void JumpInToEvent(EventFromAPIModel eventFromAPI)
 329    {
 1330        Vector2Int coords = new Vector2Int(eventFromAPI.coordinates[0], eventFromAPI.coordinates[1]);
 1331        string[] realmFromAPI = string.IsNullOrEmpty(eventFromAPI.realm) ? new string[] { "", "" } : eventFromAPI.realm.
 1332        string serverName = realmFromAPI[0];
 1333        string layerName = realmFromAPI[1];
 334
 1335        if (string.IsNullOrEmpty(serverName))
 1336            WebInterface.GoTo(coords.x, coords.y);
 337        else
 0338            WebInterface.JumpIn(coords.x, coords.y, serverName, layerName);
 339
 1340        view.HideEventModal();
 1341        OnCloseExploreV2?.Invoke();
 1342        OnAnyActionExecuted?.Invoke();
 343
 1344        exploreV2Analytics.SendEventTeleport(eventFromAPI.id, eventFromAPI.name, coords);
 1345    }
 346
 347    internal void SubscribeToEvent(string eventId)
 348    {
 349        // TODO (Santi): Remove when the RegisterAttendEvent POST is available.
 0350        WebInterface.OpenURL(string.Format(EVENT_DETAIL_URL, eventId));
 351
 352        // TODO (Santi): Waiting for the new version of the Events API where we will be able to send a signed POST to re
 353        //eventsAPIApiController.RegisterAttendEvent(
 354        //    eventId,
 355        //    true,
 356        //    () =>
 357        //    {
 358        //        // ...
 359        //    },
 360        //    (error) =>
 361        //    {
 362        //        Debug.LogError($"Error posting 'attend' message to the API: {error}");
 363        //    });
 364
 0365        OnAnyActionExecuted?.Invoke();
 0366    }
 367
 368    internal void UnsubscribeToEvent(string eventId)
 369    {
 370        // TODO (Santi): Remove when the RegisterAttendEvent POST is available.
 0371        WebInterface.OpenURL(string.Format(EVENT_DETAIL_URL, eventId));
 372
 373        // TODO (Santi): Waiting for the new version of the Events API where we will be able to send a signed POST to un
 374        //eventsAPIApiController.RegisterAttendEvent(
 375        //    eventId,
 376        //    false,
 377        //    () =>
 378        //    {
 379        //        // ...
 380        //    },
 381        //    (error) =>
 382        //    {
 383        //        Debug.LogError($"Error posting 'attend' message to the API: {error}");
 384        //    });
 385
 0386        OnAnyActionExecuted?.Invoke();
 0387    }
 388}