149 lines
4.9 KiB
C#
149 lines
4.9 KiB
C#
using EscapeRoomEngine.Engine.Runtime.Modules;
|
|
using EscapeRoomEngine.Engine.Runtime.UI;
|
|
using Realms;
|
|
using UnityEngine;
|
|
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
|
|
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;
|
|
|
|
namespace EscapeRoomEngine.Engine.Runtime.Measurements
|
|
{
|
|
/// <summary>
|
|
/// The storage engine that manages the data in a realm database.
|
|
/// </summary>
|
|
public class PuzzleStorage : MonoBehaviour
|
|
{
|
|
/// <summary>
|
|
/// The schema version must be updated whenever the schema in the database changed.
|
|
/// </summary>
|
|
private const int SchemaVersion = 2;
|
|
|
|
/// <summary>
|
|
/// The active instance of the storage engine.
|
|
/// </summary>
|
|
public static PuzzleStorage Instance { get; private set; }
|
|
|
|
[Tooltip("The path of the database relative to where the engine stores persistent data.")]
|
|
[SerializeField]
|
|
private string databasePath = "measurements.realm";
|
|
|
|
private Realm _realm;
|
|
|
|
private void OnEnable()
|
|
{
|
|
// configure special actions during specific migrations of the database
|
|
var config = new RealmConfiguration
|
|
{
|
|
SchemaVersion = SchemaVersion,
|
|
MigrationCallback = (migration, oldSchemaVersion) =>
|
|
{
|
|
if (oldSchemaVersion < 1)
|
|
{
|
|
// migration from version 0 to 1
|
|
// nothing to do
|
|
}
|
|
if (oldSchemaVersion < 2)
|
|
{
|
|
// migration from version 1 to 2
|
|
// nothing to do
|
|
}
|
|
|
|
Logger.Log($"Migrated database to version {SchemaVersion}", LogType.Measuring);
|
|
}
|
|
};
|
|
_realm = Realm.GetInstance(config.ConfigWithPath(databasePath));
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
Instance = this;
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
Logger.Log($"Using realm database at {_realm.Config.DatabasePath}", LogType.Measuring);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
_realm?.Dispose();
|
|
}
|
|
|
|
#region Session
|
|
|
|
/// <summary>
|
|
/// End a session and store it to the database.
|
|
/// </summary>
|
|
public void EndSession(Session session, float time)
|
|
{
|
|
session.Time = time;
|
|
|
|
_realm.Write(() => _realm.Add(session));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Puzzles
|
|
|
|
/// <summary>
|
|
/// Create a new puzzle for a specific description and store it in the database.
|
|
/// </summary>
|
|
/// <remarks>This requires that the puzzle does not yet exist in the database.</remarks>
|
|
public Puzzle New(PuzzleModuleDescription puzzle)
|
|
{
|
|
Puzzle created = null;
|
|
|
|
_realm.Write(() => created = _realm.Add(new Puzzle(puzzle)));
|
|
|
|
return created;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load a specific puzzle from the database or create it if it wasn't found.
|
|
/// </summary>
|
|
public Puzzle LoadOrNew(PuzzleModuleDescription puzzle) => _realm.Find<Puzzle>(puzzle.Id) ?? New(puzzle);
|
|
|
|
/// <summary>
|
|
/// Load a specific puzzle from the database.
|
|
/// </summary>
|
|
/// <returns>The puzzle or null if it wasn't found in the database.</returns>
|
|
public Puzzle Load(PuzzleModuleDescription puzzle) => _realm.Find<Puzzle>(puzzle.Id);
|
|
|
|
/// <summary>
|
|
/// Delete all records concerning a specific puzzle from the database irreversibly.
|
|
/// </summary>
|
|
public void Delete(PuzzleModuleDescription puzzle)
|
|
{
|
|
var found = Load(puzzle);
|
|
if (found != null)
|
|
{
|
|
_realm.Write(() => _realm.Remove(found));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// End the measurement for a specific puzzle and store it in the database. Also stores the results of the current puzzle plan.
|
|
/// </summary>
|
|
public void EndMeasurement(Session session, PuzzleModuleDescription puzzle, PuzzleMeasurement measurement)
|
|
{
|
|
var found = LoadOrNew(puzzle);
|
|
|
|
_realm.Write(() =>
|
|
{
|
|
measurement.TimeSolved = Time.time;
|
|
found.Measurements.Add(measurement);
|
|
|
|
// add solved puzzle to session
|
|
session.PuzzlesSolved.Add(found);
|
|
|
|
// add plan result to session
|
|
var percentile = found.Distribution.Cumulative(measurement.Time);
|
|
session.PlanResults.Add(new PlanResult(
|
|
GameControl.Instance.TargetTime,
|
|
percentile,
|
|
GameControl.Instance.EstimatedTime));
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |