消防培训系统服务器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
6.0 KiB

//using AX.CloudDrive.Hubs;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace AX.FireTrainingSys.Services
{
/// <summary>
/// 房间计时器管理。
/// </summary>
public class GroupTimerManager
{
private ConcurrentDictionary<string, GroupTimer> timers = new ConcurrentDictionary<string, GroupTimer>();
//private readonly IHubContext<SandboxHub> hubContext;
private Timer timer;
private int timerEnable = 0;
private bool TimerEnable
{
get
{
return Interlocked.CompareExchange(ref timerEnable, 1, 1) == 1;
}
set
{
if (value)
Interlocked.CompareExchange(ref timerEnable, 1, 0);
else
Interlocked.CompareExchange(ref timerEnable, 0, 1);
}
}
//public GroupTimerManager(IHubContext<SandboxHub> hubContext)
//{
// this.hubContext = hubContext;
//}
//计时器回调
//private async void OnElapsedTime(object state)
//{
// foreach (var pair in timers)
// {
// var groupName = pair.Key;
// var group = pair.Value;
// group.ElapsedTime += TimeSpan.FromSeconds(1);
// var time = group.ElapsedTime;
// await hubContext.Clients.Group(groupName).SendAsync("TimeSync", time.Ticks);
// }
//}
//public void StartTimer(string groupName)
//{
// if (!TimerEnable)
// {
// timer ??= new Timer(OnElapsedTime);
// timer?.Change(0, 1000);
// }
// var groupTimer = timers.GetOrAdd(groupName, new GroupTimer());
// groupTimer.Start();
//}
public void StopTimer(string groupName)
{
if (timers.TryGetValue(groupName, out var groupTimer))
groupTimer.Stop();
}
public void RemoveTimer(string groupName)
{
timers.TryRemove(groupName, out _);
if (timers.IsEmpty)
{
timer?.Change(Timeout.Infinite, Timeout.Infinite);
TimerEnable = false;
}
}
public GroupTimer Timer(string groupName)
{
timers.TryGetValue(groupName, out var groupTimer);
return groupTimer;
}
}
/// <summary>
/// 房间计时器。
/// </summary>
public class GroupTimer
{
private DateTimeOffset time;
private TimeSpan realElapsedTime;
private TimeSpan elapsedTime;
private bool started;
private bool paused;
private bool over;
private object obj = new object();
/// <summary>
/// 时序。
/// </summary>
public List<DateTimeOffset> TimeSeries { get; private set; } = new List<DateTimeOffset>();
/// <summary>
/// 真实流逝的时间。
/// </summary>
public TimeSpan RealElapsedTime
{
get
{
lock (obj)
{
if (started && !paused && !over)
{
var now = DateTimeOffset.Now;
realElapsedTime += now - time;
time = now;
}
return realElapsedTime;
}
}
}
/// <summary>
/// 流逝的时间。
/// </summary>
public TimeSpan ElapsedTime
{
get
{
lock (obj) { return elapsedTime; }
}
set
{
lock(obj)
{
if (started && !paused && !over)
elapsedTime = value;
}
}
}
/// <summary>
/// 开始时间。
/// </summary>
public DateTimeOffset StartingTime
{
get { lock (obj) { return TimeSeries[0]; } }
}
/// <summary>
/// 结束时间。
/// </summary>
public DateTimeOffset EndTime => TimeSeries[^1];
public (DateTimeOffset, bool) Start()
{
lock (obj)
{
if (!started)
{
started = true;
time = Timing();
realElapsedTime = TimeSpan.Zero;
}
return (time, started);
}
}
public (DateTimeOffset, bool) Pause()
{
lock (obj)
{
if (started && !paused)
{
paused = true;
var now = Timing();
realElapsedTime += now - time;
time = now;
}
return (time, paused);
}
}
public (DateTimeOffset, bool) Resume()
{
lock (obj)
{
if (started && paused)
{
paused = false;
time = Timing();
}
return (time, paused);
}
}
public (DateTimeOffset, bool) Stop()
{
lock (obj)
{
if (started && !over)
{
over = true;
var now = Timing();
realElapsedTime += now - time;
time = now;
}
return (time, over);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private DateTimeOffset Timing()
{
var now = DateTimeOffset.Now;
TimeSeries.Add(now);
return now;
}
}
}