Skip to content

Commit

Permalink
*add data
Browse files Browse the repository at this point in the history
  • Loading branch information
aprius committed Nov 27, 2022
1 parent 05e593c commit 2d49b24
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 81 deletions.
3 changes: 3 additions & 0 deletions Runtime/Common/Error.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public static void ThrowWhenContinuationIsAlreadyRegistered<T>(T continuationFie
[MethodImpl(MethodImplOptions.NoInlining)]
internal static Exception NoMatch() { return new InvalidOperationException("Sequence contains no matching element"); }

[MethodImpl(MethodImplOptions.NoInlining)]
internal static Exception NotFound(string key) { return new Exception($"No data saved with key: {key}");}

[MethodImpl(MethodImplOptions.NoInlining)]
internal static Exception NotSupported() { return new NotSupportedException(); }
}
Expand Down
142 changes: 142 additions & 0 deletions Runtime/Core/Data.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.IO;
using Pancake.OdinSerializer;
using UnityEngine;

namespace Pancake
{
/// <summary>
///
/// </summary>
public static class Data
{
[Serializable]
private sealed class DataSegment
{
public byte[] value;
}

private static bool isInitialized;
private static string path = string.Empty;
private static int profile;
private static Dictionary<string, DataSegment> datas;
private const int INIT_SIZE = 64;
private const DataFormat FORMAT = DataFormat.Binary;

public static event Action OnSaveEvent;

#region Internal Stuff

internal static void Init()
{
if (isInitialized) return;
isInitialized = true;

GeneratePath();
Load();
RuntimeHelper.AddFocusCallback(OnApplicationFocus);
}

private static byte[] Serialize<T>(T data)
{
byte[] bytes = SerializationUtility.SerializeValue(data, FORMAT);
return bytes;
}

private static T Deserialize<T>(byte[] bytes)
{
var data = SerializationUtility.DeserializeValue<T>(bytes, FORMAT);
return data;
}

private static void GeneratePath() { path = Path.Combine(Application.persistentDataPath, $"masterdata_{profile}.data"); }

private static void OnApplicationFocus(bool focus)
{
if (!focus)
{
Save();
}
}

#endregion

#region Public API

public static void ChangeProfile(int value)
{
if (profile == value) return;

Save();
profile = value;
GeneratePath();
Load();
}

public static void Save()
{
OnSaveEvent?.Invoke();

byte[] bytes = Serialize(datas);
File.WriteAllBytes(path, bytes);
}

public static void Load()
{
if (!path.FileExists())
{
var stream = File.Create(path);
stream?.Close();
}

byte[] bytes = File.ReadAllBytes(path);
datas = Deserialize<Dictionary<string, DataSegment>>(bytes) ?? new Dictionary<string, DataSegment>(INIT_SIZE);
}

public static T Load<T>(string key)
{
datas.TryGetValue(key, out var value);
if (value == null) throw Error.NotFound(key);
return Deserialize<T>(value.value);
}

public static bool TryLoad<T>(string key, out T data)
{
bool hasKey;
if (datas.TryGetValue(key, out var value))
{
data = Deserialize<T>(value.value);
hasKey = true;
}
else
{
data = default;
hasKey = false;
}

return hasKey;
}

public static void Save<T>(string key, T data)
{
if (datas.TryGetValue(key, out var value))
{
value.value = Serialize<T>(data);
}
else
{
var dataSegment = new DataSegment {value = Serialize<T>(data)};
datas.Add(key, dataSegment);
}
}

public static bool HasKey(string key) => datas.ContainsKey(key);

public static void DeleteKey(string key) => datas.Remove(key);

public static void DeleteAll() => datas.Clear();

#endregion
}
}
3 changes: 3 additions & 0 deletions Runtime/Core/Data.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

95 changes: 95 additions & 0 deletions Runtime/Core/DeviceLogTracking.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System;
using System.Globalization;
using System.IO;
using System.Text;
using UnityEngine;

namespace Pancake
{
public static class DeviceLogTracking
{
private static bool isInitialized;
public static StringBuilder sessionLogError;

internal static void Init()
{
if (isInitialized) return;
isInitialized = true;
// tracking log
sessionLogError = new StringBuilder();
Application.logMessageReceived -= OnHandleLogReceived;
Application.logMessageReceived += OnHandleLogReceived;
RuntimeHelper.AddQuitCallback(OnApplicationQuit);
}

/// <summary>
/// handle when receive log
/// </summary>
/// <param name="log"></param>
/// <param name="stacktrace"></param>
/// <param name="type"></param>
private static void OnHandleLogReceived(string log, string stacktrace, LogType type)
{
if (type == LogType.Exception || type == LogType.Error)
{
sessionLogError.AppendLine(log);
sessionLogError.AppendLine(stacktrace);
}
}

private static void OnApplicationQuit()
{
// remove old log outdate
RemoveOldLogDirectory(3);

// write current log
WriteLocalLog();
}

/// <summary>
/// write log to local file
/// </summary>
/// <returns></returns>
private static string WriteLocalLog()
{
var log = sessionLogError.ToString();
if (!string.IsNullOrEmpty(log))
{
// create the directory
var feedbackDirectory = $"{Application.persistentDataPath}/userlogs/{DateTime.Now:ddMMyyyy}/{DateTime.Now:HHmmss}";
if (!feedbackDirectory.DirectoryExists()) feedbackDirectory.CreateDirectory();

// save the log
File.WriteAllText(feedbackDirectory + "/logs.txt", log);

return feedbackDirectory;
}

return "";
}

/// <summary>
/// Removes stale logs that exceed the number of days specified by <paramref name="day"/>
/// </summary>
/// <param name="day"></param>
private static void RemoveOldLogDirectory(int day)
{
var path = $"{Application.persistentDataPath}/userlogs";
if (path.DirectoryExists())
{
DirectoryInfo info = new DirectoryInfo(path);
foreach (var directoryInfo in info.GetDirectories())
{
string folderName = directoryInfo.Name;
DateTime.TryParseExact(folderName,
"ddMMyyyy",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out var dateTime);

if ((DateTime.Now - dateTime).TotalDays >= day) $"{path}/{folderName}".DeleteDirectory();
}
}
}
}
}
3 changes: 3 additions & 0 deletions Runtime/Core/DeviceLogTracking.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 3 additions & 80 deletions Runtime/Core/RuntimeManager.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Globalization;
using System.Text;
using System.IO;
using UnityEngine;
using Object = UnityEngine.Object;

Expand All @@ -14,7 +11,6 @@ public static class RuntimeManager

private static bool isInitialized;

public static StringBuilder sessionLogError;

#region Public API

Expand All @@ -34,16 +30,13 @@ private static void Init()

if (Application.isPlaying)
{
// tracking log
sessionLogError = new StringBuilder();
Application.logMessageReceived -= OnHandleLogReceived;
Application.logMessageReceived += OnHandleLogReceived;

// Initialize runtime Helper.
var runtimeHelper = new GameObject("RuntimeHelper") {hideFlags = HideFlags.HideInHierarchy};
runtimeHelper.AddComponent<RuntimeHelper>();
Object.DontDestroyOnLoad(runtimeHelper);
RuntimeHelper.AddQuitCallback(OnApplicationQuit);

DeviceLogTracking.Init();
Data.Init();

if (Monetization.AdSettings.RuntimeAutoInitialize) AdConfigure(runtimeHelper);

Expand Down Expand Up @@ -104,76 +97,6 @@ private static void AdConfigure(GameObject go)
#endif
}

/// <summary>
/// handle when receive log
/// </summary>
/// <param name="log"></param>
/// <param name="stacktrace"></param>
/// <param name="type"></param>
private static void OnHandleLogReceived(string log, string stacktrace, LogType type)
{
if (type == LogType.Exception || type == LogType.Error)
{
sessionLogError.AppendLine(log);
sessionLogError.AppendLine(stacktrace);
}
}

private static void OnApplicationQuit()
{
// remove old log outdate
RemoveOldLogDirectory(3);

// write current log
WriteLocalLog();
}

/// <summary>
/// write log to local file
/// </summary>
/// <returns></returns>
private static string WriteLocalLog()
{
var log = sessionLogError.ToString();
if (!string.IsNullOrEmpty(log))
{
// create the directory
var feedbackDirectory = $"{Application.persistentDataPath}/userlogs/{DateTime.Now:ddMMyyyy}/{DateTime.Now:HHmmss}";
if (!feedbackDirectory.DirectoryExists()) feedbackDirectory.CreateDirectory();

// save the log
File.WriteAllText(feedbackDirectory + "/logs.txt", log);

return feedbackDirectory;
}

return "";
}

/// <summary>
/// Removes stale logs that exceed the number of days specified by <paramref name="day"/>
/// </summary>
/// <param name="day"></param>
private static void RemoveOldLogDirectory(int day)
{
var path = $"{Application.persistentDataPath}/userlogs";
if (path.DirectoryExists())
{
DirectoryInfo info = new DirectoryInfo(path);
foreach (var directoryInfo in info.GetDirectories())
{
string folderName = directoryInfo.Name;
DateTime.TryParseExact(folderName,
"ddMMyyyy",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out var dateTime);

if ((DateTime.Now - dateTime).TotalDays >= day) $"{path}/{folderName}".DeleteDirectory();
}
}
}

#endregion
}
}
2 changes: 1 addition & 1 deletion Samples~/Feedback/Scripts/DebugLogCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public override void Collect()
}

// attach log
oldLog.AppendLine(RuntimeManager.sessionLogError.ToString());
oldLog.AppendLine(DeviceLogTracking.sessionLogError.ToString());
byte[] bytes = Encoding.ASCII.GetBytes(oldLog.ToString());
popupFeedback.report.AttachFile("log.txt", bytes);
}
Expand Down

0 comments on commit 2d49b24

Please sign in to comment.