using Logger;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Threading;
using UnityEngine;
namespace Networkreader
{
public class NWreader :AbstractNWReader, INWReader
{
#region Parameter
private readonly int ROWLENGTHINBYTES = 3 * sizeof(Int32) + 1 * sizeof(Double) + 9 * sizeof(Single) + 2 * sizeof(UInt32);
///
/// The time(in ms) data is buffered befor it is sorted and written to file.
///
private double BufferTime { get; set; }
///
/// A buffer for data containing the timestamp of the date and the the object as byte[] rep.
///
private List> Buffer { get; set; }
///
/// Holds the latest read timestamp.
///
private double NewestTimeStamp;
///
/// Holds the first read timestamp.
///
private double OldestTimeStamp;
#endregion
#region Constructor
public NWreader(string ipAdress, int port, double buffertime) : base(ipAdress, port)
{
this.BufferTime = buffertime;
this.Buffer = new List>();
this.NewestTimeStamp = 0;
this.OldestTimeStamp = double.NaN;
}
#endregion
#region Exposed
///
/// Returns the newest timestamp that was written to the file.
///
///
public double GetNewestTimestamp()
{
return NewestTimeStamp;
}
///
/// Returns the first timestamp that was written to the file.
///
///
public double GetOldestTimestamp()
{
return OldestTimeStamp;
}
#endregion
#region Internal
private bool IsOutdated(Tuple elem)
{
return elem.Item1 < NewestTimeStamp;
}
///
/// A Thread that reads data from , stores it in and calls after .
///
/// Filepath of the .bin file.
protected override void WriteToFileThread(object filepath)
{
Streaming = true;
NWStream = Client.GetStream();
Stopwatch watch = new Stopwatch();
double lastWritten = 0;
byte[] buffer;
watch.Start();
while (Streaming)
{
try
{
if (NWStream.DataAvailable)
{
buffer = new byte[ROWLENGTHINBYTES];
ReadBuffer(buffer);
//the timestamp is always at the second position of the bytearray adter the ID of the object
double timestamp = BitConverter.ToDouble(buffer, sizeof(int));
Buffer.Add(Tuple.Create(timestamp, buffer));
}
else
Thread.Sleep(10);
}
catch (Exception e)
{
CityLogger.LogWarning("Unable to read data from NW stream with error: " + e.Message);
return;
}
if (lastWritten + watch.ElapsedMilliseconds > BufferTime)
{
lastWritten = 0;
DumpBuffer(filepath.ToString());
watch.Restart();
}
}
Client.Close();
}
///
/// Dumps to filepath.
///
/// Filepath of the .bin file.
private void DumpBuffer(string filepath)
{
//Sort the buffered elements so that they will be saved in the right time order
Buffer.Sort((a, b) => a.Item1.CompareTo(b.Item1));
//and delete the one that are outdated
int deleted = 0;
if (Buffer.Count > 0)
deleted = Buffer.RemoveAll(IsOutdated);
if (deleted > 0)
CityLogger.Log("Some timestamps came after their time: " + deleted, LogLevel.INFO);
using (BinaryWriter sw = new BinaryWriter(new FileStream(filepath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)))
foreach (Tuple line in Buffer)
sw.Write(line.Item2, 0, line.Item2.Length);
if (Buffer.Count >= 1)
NewestTimeStamp = Buffer.Last().Item1;
if (double.IsNaN(OldestTimeStamp) && Buffer.Count >= 1)
OldestTimeStamp = Buffer.First().Item1;
Buffer.Clear();
}
protected override string GetFilename()
{
return "Stream_" + DateTime.Now.ToString(new CultureInfo("de-DE")).Replace(" ", "_").Replace(":", ".") + ".bin";
}
#endregion
}
}