Skip to content

Commit

Permalink
Merge pull request #62 from bjrtx/main
Browse files Browse the repository at this point in the history
Start rewriting Socket.cs
  • Loading branch information
bjrtx authored May 2, 2024
2 parents faab926 + 2f73958 commit 6a9da57
Show file tree
Hide file tree
Showing 23 changed files with 251 additions and 165 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace VHToolkit.Calibration {

public class QuickCalibration : MonoBehaviour {

[SerializeField] private Transform physicalHead;
[SerializeField] private Transform world;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ private void Update() {
}

/// <summary>
/// This function sets the state of the calibration so that the user can start calibration on the next frame
/// Function <c>Calibrate</c> sets the state of the calibration so that the user can start calibration on the next frame.
/// </summary>
public void Calibrate() => state = CalibrationState.FirstPoint;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.IO;
using UnityEngine;

namespace VHToolkit.Logging {
abstract class AbstractFileObserver<T> : IObserver<T> {
protected readonly StreamWriter writer;
private IDisposable unsubscriber;
public void OnCompleted() {
unsubscriber.Dispose();
writer.Dispose();
}

public void Subscribe(IObservable<T> observable) => unsubscriber = observable?.Subscribe(this);

public void OnError(Exception error) => Debug.LogError(error);

abstract public void OnNext(T value);

public AbstractFileObserver(string filename) {
writer = new StreamWriter(filename, append: true);
}
}
}

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

Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,23 @@
using Newtonsoft.Json;

namespace VHToolkit.Logging {

/// <summary>
/// Record type <c>TransformData</c> is a wrapper around Unity's <c>Transform</c>.
/// It allows for serializing the underlying <c>Transform</c>'s <c>position</c> and <c>rotation</c> properties.
/// </summary>
public record TransformData {
private readonly Transform obj;
public string Position => obj ? obj.position.ToString() : "NULL";
public string Orientation => obj ? obj.rotation.normalized.ToString() : "NULL";
public TransformData(Transform obj) => this.obj = obj;
}

/// <summary>
/// Record type <c>PhysicalLimbData</c> is a wrapper around <c>Limb</c>.
/// It allows for serializing the <c>position</c> and <c>rotation</c> properties of the underlying physical limb,
/// as well as those of all underlying virtual limbs.
/// </summary>
public record PhysicalLimbData {
private readonly Limb limb;
public string Position => limb.physicalLimb.position.ToString();
Expand All @@ -30,17 +40,26 @@ public record JsonRedirectionData {
public readonly DateTime TimeStamp = DateTime.Now;
private readonly Interaction script;

public string Technique => script switch {
/// <value>
/// Property <c>Strategy</c> is a string corresponding to the name of the current World Redirection
/// target selection strategy, if any, or the empty string.
/// </value>
public string Strategy => script switch {
WorldRedirection => (script as WorldRedirection).strategy.ToString(),
BodyRedirection => "",
_ => ""
BodyRedirection => String.Empty,
_ => String.Empty
};

public string Strategy => script switch {
/// <value>
/// Property <c>Technique</c> is a string corresponding to the name of the current redirection
/// technique, if any, or the empty string.
/// </value>
public string Technique => script switch {
WorldRedirection => (script as WorldRedirection).Technique.ToString(),
BodyRedirection => (script as BodyRedirection).Technique.ToString(),
_ => ""
};

public bool Redirecting => script.redirect;

public List<PhysicalLimbData> Limbs => script.scene.limbs.ConvertAll(l => new PhysicalLimbData(l));
Expand All @@ -53,44 +72,6 @@ public record JsonRedirectionData {
public JsonRedirectionData(Interaction script) => this.script = script;
}

public class Logger<T> : MonoBehaviour, IObservable<T> {
public string logDirectoryPath = "LoggedData\\";
[SerializeField] protected string optionalFilenamePrefix;
protected readonly int bufferSize = 10; // number of records kept before writing to disk

protected Queue<T> records = new();
protected HashSet<IObserver<T>> observers = new();
protected Interaction script;

protected void WriteRecords(Queue<T> records) {
if (records.Count > bufferSize) {
foreach (var record in records) {
foreach (var observer in observers) {
observer.OnNext(record);
}
}
records.Clear();
}
}

private sealed class Unsubscriber : IDisposable {
private readonly HashSet<IObserver<T>> _observers;
private readonly IObserver<T> _observer;

public Unsubscriber(HashSet<IObserver<T>> observers, IObserver<T> observer) {
_observers = observers;
_observer = observer;
}

public void Dispose() => _observers.Remove(_observer);
}

IDisposable IObservable<T>.Subscribe(IObserver<T> observer) {
observers.Add(observer);
return new Unsubscriber(observers, observer);
}
}

/// <summary>
/// Logs structured data in the JSON Lines format.
/// </summary>
Expand All @@ -105,31 +86,27 @@ private void Update() {
records.Enqueue(new JsonRedirectionData(script));
WriteRecords(records);
}

/// <summary>
/// Create a new log file.
/// </summary>
/// <param name="logDirectoryPath">The path to the directory where the file should be placed.</param>
/// <param name="optionalFilenamePrefix">An optional prefix string to appear in the filename before its timestamp.</param>
public void CreateNewFile(string logDirectoryPath, string optionalFilenamePrefix = "") {
Directory.CreateDirectory(logDirectoryPath);
var fileName = $"{logDirectoryPath}{optionalFilenamePrefix}{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.jsonl";
var observer = new FileObserver(fileName);
var observer = new JsonFileObserver(fileName);
observer.Subscribe(this);
observers.Add(observer);
}

/// <summary>
/// The class <c>JsonFileObserver</c> implements the Observer pattern for <c>JsonRedirectionData</c> instances,
/// serializing the information which it receives and writing it to a file.
/// </summary>
private sealed class JsonFileObserver : AbstractFileObserver<JsonRedirectionData> {
public JsonFileObserver(string filename) : base(filename) { }

private sealed class FileObserver : IObserver<JsonRedirectionData> {
private readonly StreamWriter writer;
private IDisposable unsubscriber;
public void OnCompleted() {
unsubscriber.Dispose();
writer.Dispose();
}

public void Subscribe(IObservable<JsonRedirectionData> observable) => unsubscriber = observable?.Subscribe(this);

public void OnError(Exception error) => Debug.LogError(error);

public void OnNext(JsonRedirectionData value) => writer.WriteLine(JsonConvert.SerializeObject(value));

public FileObserver(string filename) => writer = new StreamWriter(filename, append: true);
override public void OnNext(JsonRedirectionData value) => writer.WriteLine(JsonConvert.SerializeObject(value));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;

using UnityEngine;

using VHToolkit.Redirection;

namespace VHToolkit.Logging {
public partial class Logger<T> : MonoBehaviour, IObservable<T> {
public string logDirectoryPath = "LoggedData\\";
[SerializeField] protected string optionalFilenamePrefix;
protected readonly int bufferSize = 10; // number of records kept before writing to disk

protected readonly Queue<T> records = new();
protected readonly HashSet<IObserver<T>> observers = new();
protected Interaction script;

protected void WriteRecords(Queue<T> records) {
if (records.Count > bufferSize) {
foreach (var record in records) {
foreach (var observer in observers) {
observer.OnNext(record);
}
}
records.Clear();
}
}

IDisposable IObservable<T>.Subscribe(IObserver<T> observer) {
observers.Add(observer);
return new HashSetUnsubscriber<T>(observers, observer);
}
}
}

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

Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@
using VHToolkit.Redirection.BodyRedirection;
using VHToolkit.Redirection.WorldRedirection;

namespace VHToolkit.Logging
{
/// <summary>
/// Class specifying loggable data for a redirection scene.
/// </summary>
public record RedirectionData {
namespace VHToolkit.Logging {
/// <summary>
/// Class specifying loggable data for a redirection scene.
/// </summary>
public record RedirectionData {
public DateTime timeStamp = DateTime.Now;
public string Technique => script switch {
WorldRedirection => (script as WorldRedirection).Technique.ToString(),
Expand Down Expand Up @@ -111,28 +110,21 @@ public void CreateNewFile(string logDirectoryPath = null, string optionalFilenam
observer.Subscribe(this);
observers.Add(observer);
}
private sealed class FileObserver : IObserver<RedirectionData> {
private StreamWriter writer;
private CsvWriter csvWriter;
private IDisposable unsubscriber;
public void OnCompleted() {
unsubscriber.Dispose();

private sealed class FileObserver : AbstractFileObserver<RedirectionData> {
private readonly CsvWriter csvWriter;
public new void OnCompleted() {
base.OnCompleted();
csvWriter.Dispose();
writer.Dispose();
}

public void Subscribe(IObservable<RedirectionData> observable) => unsubscriber = observable?.Subscribe(this);

public void OnError(Exception error) => Debug.LogError(error);

public void OnNext(RedirectionData value) {
public override void OnNext(RedirectionData value) {
csvWriter.Context.RegisterClassMap<RedirectionDataMap>();
csvWriter.WriteRecord(value);
csvWriter.NextRecord();
}

public FileObserver(string filename, CsvConfiguration config) {
writer = new StreamWriter(filename, append: true);
public FileObserver(string filename, CsvConfiguration config) : base(filename) {
csvWriter = new(writer, configuration: config);
csvWriter.Context.RegisterClassMap<RedirectionDataMap>();
csvWriter.WriteHeader<RedirectionData>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;

namespace VHToolkit.Logging {
sealed class HashSetUnsubscriber<T> : IDisposable {
private readonly HashSet<IObserver<T>> _observers;
private readonly IObserver<T> _observer;

public HashSetUnsubscriber(HashSet<IObserver<T>> observers, IObserver<T> observer) {
_observers = observers;
_observer = observer;
}

public void Dispose() => _observers.Remove(_observer);
}
}

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

Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using UnityEngine;

namespace VHToolkit.Redirection {
namespace VHToolkit.Redirection {
abstract public class RedirectionTechnique {
/// <summary>
/// This abstract method redirects the Scene transforms according to the other parameters and the equations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace VHToolkit.Redirection {

/// <summary>
/// A Limb pairs one <c>physicalLimb</c> Transform with a list of virtual limb Transforms.
/// A <c>Limb</c> pairs one <c>physicalLimb</c> Transform with a list of virtual limb Transforms.
/// </summary>
[Serializable]
public struct Limb {
Expand Down Expand Up @@ -42,7 +42,7 @@ public Limb(Transform physicalLimb, List<Transform> virtualLimb) {
public record Scene {
[SerializeField] public List<Limb> limbs;

[Ignore] public List<Transform> virtualLimbs => limbs.SelectMany(limb => limb.virtualLimb).ToList();
[Ignore] public List<Transform> VirtualLimbs => limbs.SelectMany(limb => limb.virtualLimb).ToList();

[Ignore] public Transform physicalHead;
[Ignore] public Transform virtualHead;
Expand Down Expand Up @@ -103,7 +103,7 @@ public List<Vector3> LimbRedirection {
public Vector3 GetHeadToHeadVector() => physicalHead.position - virtualHead.position;

private Quaternion _redirection = Quaternion.identity;
/// <returns>The quaternion rotation between the user's physical and virtual head.</returns>
/// <value>The quaternion rotation between the user's physical and virtual head.</value>
public Quaternion HeadToHeadRedirection {
get => _redirection;
set { virtualHead.rotation = value * physicalHead.rotation; _redirection = value; }
Expand Down Expand Up @@ -161,6 +161,5 @@ public void CopyLimbTranslationAndRotation() => limbs.ForEach(limb => {
/// </summary>
public void RotateVirtualHeadY(float angle) => HeadToHeadRedirection = Quaternion.Euler(0f, angle, 0f) * HeadToHeadRedirection;

public List<Collider2D> GetAllObstaclesCollider() => GameObject.FindGameObjectsWithTag("Obstacle").Select(v => v.GetComponent<Collider2D>()).ToList();
}
}
Loading

0 comments on commit 6a9da57

Please sign in to comment.