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
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; |
|
} |
|
} |
|
}
|
|
|