using System; using System.Collections.Generic; using System.Threading.Tasks; using Plugins.Countly.Helpers; using Plugins.Countly.Models; using UnityEngine; namespace Plugins.Countly.Services.Impls.Actual { public class ViewCountlyService : IViewCountlyService { private readonly Dictionary _viewToLastViewStartTime = new Dictionary(); private readonly IEventCountlyService _eventService; public ViewCountlyService(IEventCountlyService eventService) { _eventService = eventService; } public async Task RecordOpenViewAsync(string name, bool hasSessionBegunWithView = false) { if (string.IsNullOrEmpty(name)) { return new CountlyResponse { IsSuccess = false, ErrorMessage = "View name is required." }; } var currentViewSegment = new ViewSegment { Name = name, Segment = Constants.UnityPlatform, Visit = 1, Exit = 0, Bounce = 0, HasSessionBegunWithView = hasSessionBegunWithView }; if (!_viewToLastViewStartTime.ContainsKey(name)) { _viewToLastViewStartTime.Add(name, DateTime.UtcNow); } Debug.Log("[ViewCountlyService] RecordOpenViewAsync: " + name); var currentView = new CountlyEventModel(CountlyEventModel.ViewEvent, currentViewSegment.ToDictionary()); return await _eventService.RecordEventAsync(currentView); } public async Task RecordCloseViewAsync(string name, bool hasSessionBegunWithView = false) { if (string.IsNullOrEmpty(name)) { return new CountlyResponse { IsSuccess = false, ErrorMessage = "View name is required." }; } var currentViewSegment = new ViewSegment { Name = name, Segment = Constants.UnityPlatform, Visit = 0, Exit = 1, Bounce = 0, HasSessionBegunWithView = hasSessionBegunWithView }; double? duration = null; if (_viewToLastViewStartTime.ContainsKey(name)) { var lastViewStartTime = _viewToLastViewStartTime[name]; duration = (DateTime.UtcNow - lastViewStartTime).TotalSeconds; _viewToLastViewStartTime.Remove(name); } Debug.Log("[ViewCountlyService] RecordCloseViewAsync: " + name + ", duration: " + duration); var currentView = new CountlyEventModel(CountlyEventModel.ViewEvent, currentViewSegment.ToDictionary(), 1, null, duration); return await _eventService.RecordEventAsync(currentView); } /// /// Reports a particular action with the specified details /// /// /// /// /// /// /// public async Task ReportActionAsync(string type, int x, int y, int width, int height) { var segment = new ActionSegment { Type = type, PositionX = x, PositionY = y, Width = width, Height = height }; return await _eventService.ReportCustomEventAsync(CountlyEventModel.ViewActionEvent, segment.ToDictionary()); } /// /// Custom Segmentation for Views related events. /// [Serializable] class ViewSegment { public string Name { get; set; } public string Segment { get; set; } public int Visit { get; set; } public int Exit { get; set; } public int Bounce { get; set; } public bool HasSessionBegunWithView { get; set; } private int Start => HasSessionBegunWithView ? 1 : 0; public IDictionary ToDictionary() { var dict = new Dictionary { {"name", Name}, {"segment", Segment}, {"exit", Exit}, {"visit", Visit}, {"start", Start}, {"bounce", Bounce} }; return dict; } } /// /// Custom Segmentation for Action related events. /// [Serializable] class ActionSegment { public string Type { get; set; } public int PositionX { get; set; } public int PositionY { get; set; } public int Width { get; set; } public int Height { get; set; } public IDictionary ToDictionary() { return new Dictionary() { {"type", Type}, {"x", PositionX}, {"y", PositionY}, {"width", Width}, {"height", Height}, }; } } } }