using MuchInfo.Chart.Data.EnumTypes;
using MuchInfo.Chart.Data.Interfaces;
using MuchInfo.Chart.Data.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace MuchInfo.Chart.DataAccess
{
///
/// 文件JSON存储
///
public class FileDataAccess : IDataAccess
{
#region Methods
#region Public Methods
///
/// 获取数据
///
/// 商品代码
/// 周期类型
/// 起始时间
/// 结束时间
/// 记录条数
public IEnumerable GetDataPoints(string symbol, CycleType cycleType, DateTime startTime, DateTime endTime, int totalCount)
{
if (string.IsNullOrWhiteSpace(symbol)) return null;
//周期为Nono,默认为Day
var filePath = CombineFilePath(symbol, (cycleType == CycleType.None ? CycleType.Day : cycleType));
if (!File.Exists(filePath)) return null;
return GetDataPoints(filePath, startTime, endTime, totalCount);
}
///
/// 获取数据
///
/// The file path.
/// 起始时间
/// 结束时间
/// 记录条数
/// IEnumerable{IBarDataPoint}.
private IEnumerable GetDataPoints(string filePath, DateTime startTime, DateTime endTime, int totalCount)
{
try
{
IList dataSoure;
//获取数据
using (StreamReader file = File.OpenText(filePath))
{
var serializer = new JsonSerializer();
try
{
dataSoure = (IList)serializer.Deserialize(file, typeof(IList));
}
catch
{
return null;
}
}
if (dataSoure == null || !dataSoure.Any()) return null;
//记录条数小于零,默认取100条
//返回数据按日间顺排序
var count = totalCount <= 0 ? 100 : totalCount;
if (startTime > endTime)
{
return dataSoure.Where(z => z.Date <= endTime)
.OrderByDescending(z => z.Date)
.Take(count).OrderBy(z => z.Date);
}
else
{
return dataSoure.Where(z => z.Date >= startTime && z.Date <= endTime)
.OrderByDescending(z => z.Date)
.Take(count).OrderBy(z => z.Date);
}
}
catch (Exception ex)
{
throw ex;
}
}
///
/// 保存数据
///
/// 商品代码
/// 周期类型
/// 保存的数据
///
public void SaveDataPoints(string symbol, CycleType cycleType, IList dataPoints)
{
if (string.IsNullOrWhiteSpace(symbol) ||
cycleType == CycleType.None ||
dataPoints == null) return;
var filePath = CombineFilePath(symbol, cycleType);
SaveDataPoints(filePath, dataPoints);
}
///
/// Saves the data points.
///
/// The file path.
/// The data points.
private void SaveDataPoints(string filePath, IList dataPoints)
{
try
{
IList totalDataPoints;
if (File.Exists(filePath))
{
//获取源数据
IList source;
try
{
using (StreamReader file = File.OpenText(filePath))
{
var serializer = new JsonSerializer();
source = (IList)serializer.Deserialize(file, typeof(IList));
}
}
catch
{
//反序列化出错,删除源文件,重新写入目标数据
source = new List();
File.Delete(filePath);
}
//合并数据
totalDataPoints = CombineDataPoints(source == null ? null : source.ToList(), dataPoints).ToList();
}
else
{
totalDataPoints = dataPoints;
var fileInfo = new FileInfo(filePath);
//创建目录
if (fileInfo.Directory != null && !Directory.Exists(fileInfo.Directory.FullName))
{
Directory.CreateDirectory(fileInfo.Directory.FullName);
}
}
//写JSON数据
using (var file = File.CreateText(filePath))
{
var serializer = new JsonSerializer();
serializer.Serialize(file, totalDataPoints);
}
}
catch (Exception ex)
{
throw ex;
}
}
#endregion Public Methods
#region Private Methods
///
/// 合并数据
///
/// 源数据
/// 目标数据
private IEnumerable CombineDataPoints(IList source, IList destination)
{
if (source == null && destination == null) return new List();
if (source == null || !source.Any()) return destination;
if (destination == null || !destination.Any()) return source;
//找出源中存的数据
var interesct = destination.Intersect(source, new DataPointComparer()).ToList();
//找出源数据中不存在的数据
var except = destination.Except(source, new DataPointComparer()).ToList();
//从源中移除要更新的数据
//合并不存在的数据
//合并更新的数据
var result = source.Except(interesct, new DataPointComparer())
.Union(except)
.Union(interesct);
return result;
}
///
/// 生成数据文件路径
///
/// 商品代码
/// Type of the cycle.
/// System.String.
private string CombineFilePath(string symbol, CycleType cycleType)
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data", symbol + "_" + cycleType.ToString() + ".txt");
}
private string CombineFilePath(string symbol, TimeSpan timeSpan)
{
var timeSpanString = timeSpan.ToString().Replace(".", "_").Replace(":", "_");
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data", symbol + "_" + timeSpanString + ".txt");
}
///
/// 依据周期和记录条生成EndTime
///
/// 时间
/// 周期
/// 记录条数
private DateTime CreateDateTime(DateTime time, CycleType type, int count)
{
switch (type)
{
case CycleType.Minute:
return time.AddMinutes(count);
case CycleType.Minute5:
return time.AddMinutes(count * 5);
case CycleType.Minute30:
return time.AddMinutes(count * 30);
case CycleType.Minute240:
return time.AddMinutes(count * 240);
case CycleType.Week:
return time.AddDays(count * 7);
case CycleType.Month:
return time.AddMonths(count);
case CycleType.Quarter:
return time.AddMonths(count * 4);
case CycleType.Year:
return time.AddYears(count);
default:
return time.AddDays(count);
}
}
#endregion Private Methods
#endregion Methods
public IEnumerable GetDataPoints(string symbol, TimeSpan timeSpan, DateTime startTime, DateTime endTime, int totalCount)
{
if (string.IsNullOrWhiteSpace(symbol)) return null;
var filePath = CombineFilePath(symbol, timeSpan);
if (!File.Exists(filePath)) return null;
return GetDataPoints(filePath, startTime, endTime, totalCount);
}
///
/// 保存数据
///
/// 商品代码
/// The time span.
/// 保存的数据
public void SaveDataPoints(string symbol, TimeSpan timeSpan, IList dataPoints)
{
if (string.IsNullOrWhiteSpace(symbol) || dataPoints == null) return;
var filePath = CombineFilePath(symbol, timeSpan);
SaveDataPoints(filePath, dataPoints);
}
}
}