using Assets.Scenes.Ride.Scripts.Model; using Assets.Scenes.Ride.Scripts.Network; using Assets.Scripts; using Assets.Scripts.Apis; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Assets.Scenes.Ride.Scripts { public class MapUDPService { private static IService _udpService; //private static UdpClient udpClient; //private static IPEndPoint iPEndPoint; private static bool isExit = false; //private static Task task = null; //private static CancellationTokenSource cts { get; set; } private static CancellationToken ct { get; set; } //private static List onlineUsers { get; set; } = new List(); private static System.Timers.Timer heartbeat { get; set; } public static bool Pause { get; set; } = false; private static OnlineUserHelper _onlineUserHelper; private static OnlineUserHelper onlineUserHelper { get { if (_onlineUserHelper == null) { _onlineUserHelper = new OnlineUserHelper(); } return _onlineUserHelper; } } private static DateTime LastActiveTime = DateTime.Now; private static List msgs = new List(); /// /// 初始化(如果UDP服务未启动,则会已没5秒一次不断尝试,直到连接上为止,前端不需要考虑任何UDP连接的事情) /// public static void Init() { try { //var ddd = new MapWorkoutService().GetRealOnlineUserInfo(new List { 6 }); isExit = false; Pause = false; if (_udpService == null) { _udpService = new TcpService1(); _udpService.Start(list => { LastActiveTime = DateTime.Now; //onlineUserHelper.RemoveExceptionData(list); msgs = list; onlineUserHelper.SetOnlineUser(msgs); }); heartbeat = new System.Timers.Timer(); heartbeat.Interval = 1000; heartbeat.AutoReset = true; heartbeat.Enabled = true; heartbeat.Elapsed += Heartbeat_Elapsed; } } catch (Exception e) { Trace.WriteLine("UDP:" + e.Message); } finally { //发送一条心跳包 //SendHeartbeat(); } } private static void Heartbeat_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { var now = DateTime.Now; //超过一秒没有收到消息 if ((now - LastActiveTime).TotalSeconds > 1) { onlineUserHelper.SetOnlineUser(new List()); } if (now.Second % 20 == 0) { //LastActiveTime = now; SendHeartbeat(); } } /// /// 发送心跳包 /// private static void SendHeartbeat() { Send(0, App.CurrentUser.Id, new double[] { 0, 0 }, false, false, 0, true, 0); } /// /// 发送数据 /// /// 路书Id /// 用户id /// 当前点位 /// 属性 /// 是否完成 /// 是否退出 public static void Send(int RouteId, int MemberId, double[] Point, bool IsCompleted = false, bool exit = false, double endDistance = 0, bool showVirtual = false, byte commandType = 1, double speed = 0, bool isVirtual = false, double preDistance = 0, double weightKg = 0, int competitionId = 0, bool saved = false) { try { var model = new MsgModel { RouteId = RouteId, MemberId = MemberId, Point = Point, IsCompleted = IsCompleted, exit = exit, EndDistance = endDistance, //ShowVirtual = showVirtual, CommandType = commandType, Speed = speed, //IsVirtual = isVirtual, PreDistance = preDistance, WeightKg = weightKg, Competitionid = competitionId, Saved = saved, V = 1 }; var sendBytes = Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(model)); _udpService.Send(sendBytes, sendBytes.Length); } catch (Exception e) { Console.WriteLine("发送失败:" + e); } } public static void Dispose() { try { isExit = true; if (MapUDPService._udpService == null) return; for (int i = 0; i < 3; i++) { Send(0, App.CurrentUser.Id, new double[] { 1, 1 }, true, isExit); } _udpService.Close(); //task.Dispose(); _udpService = null; _onlineUserHelper = null; } catch (Exception) { } finally { //停止计时 if (heartbeat != null) { heartbeat.Stop(); heartbeat.Close(); } } } public static OnlineUser GetOnlineUserLastDataById(int userId) { //return _onlineUserHelper.GetOnlineUserLastDataById(userId); //var msg = msgs.Where(m => m.MemberId == userId); //if (msg == null) return null; return onlineUserHelper.OnlineUsers.FirstOrDefault(u => u.Id == userId); } /// /// 根据路书获取在线用户 /// /// /// public static List GetOnlineUsers(params int[] routeId) { //return onlineUsers.Where(n => routeId.Contains(n.RouteId)).ToList(); var result = onlineUserHelper.OnlineUsers.Where(u => routeId.Contains(u.RouteId)).ToList(); return result; } public static int GetNearRiderCount() { return onlineUserHelper.OnlineUsers.Count(); } /// /// 获取附近的人(当前在线的所有人) /// /// public static IList GetNearRiderData(int pageIndex, int pageSize = 5, double[] point = null) { if (point == null) return null; var dict = new List>(); var allOnlineUsers = onlineUserHelper.OnlineUsers; foreach (var item in allOnlineUsers) { if (item.Id == App.CurrentUser.Id) { dict.Add(new Tuple(0, item)); continue; } if (item.Point[0] != 0 && item.Point[1] != 0) { var distance = Math.Round(TurfHelper.GetDistances(point, item.Point) / 1000, 2); dict.Add(new Tuple(distance, item)); } } var allList = dict.OrderBy(d => d.Item1);//.Select(d=>d.Item2); var list = allList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); var nearData = list.Select(n => new NearRiderModel() { Headimage = n.Item2.HeadImage, Name = n.Item2.Name, Near = n.Item1, //Math.Round(TurfHelper.GetDistances(point, n.Point) / 1000, 2), KGWeight = n.Item2.WeightKg.ToString(), Speed = Math.Round(n.Item2.Speed, 1), CountryImg = App.Host + $"User/GetCountryImg?userid={n.Item2.Id}", IsSelf = n.Item2.IsSelf, Id = n.Item2.Id, Country = n.Item2.Country, }).ToList(); return nearData; //return new //{ // NearData = nearData, // PageCount = (int)Math.Ceiling((double)allList.Count() / pageSize) //}; } private class OnlineUserHelper { //public static List users { get; private set; } private static readonly object locker = new object(); private readonly List onlineUsers = new List(); public List OnlineUsers { get { //if((DateTime.Now - LastActiveTime).TotalSeconds > 1) //{ // SetOnlineUser(new List()); //} return onlineUsers.ToList(); } } /// /// 设置在线的人员 /// public void SetOnlineUser(List mes) { try { var msgs = RemoveExceptionData(mes); //LastActiveTime = DateTime.Now; var ids = msgs.Where(m => onlineUsers.All(u => u.Id != m.MemberId)).Select(m => m.MemberId); if (ids.Any()) { MapApi api = new MapApi(); var rangeUser = api.GetOnlineUserInfo(ids).data; onlineUsers.AddRange(rangeUser); } foreach (var user in onlineUsers) { var item = msgs.FirstOrDefault(u => u.MemberId == user.Id); if (item != null) { user.LastActiveTime = DateTime.Now; user.RouteId = item.RouteId; user.Point = item.Point; user.IsCompleted = item.IsCompleted; //user.exit = item.exit; user.EndDistance = item.EndDistance; user.IsVirtual = item.MemberId < 0; user.Speed = item.Speed; user.WeightKg = item.WeightKg; user.PreDistance = item.PreDistance; user.CompetitionId = item.Competitionid; user.Saved = item.Saved; } else { user.PreDistance = user.EndDistance; } } onlineUsers.RemoveAll(u => u.IsLost); } catch (Exception) { #if DEBUG throw; #endif //return new List(); } } /// /// 去除重复数据,去除坐标为0的数据 /// /// private List RemoveExceptionData(List mes) { var list = mes.ToList(); //去除自己的数据和命令包 //mes.RemoveAll(item => item.MemberId == App.CurrentUser.Id || item.Point[0] == 0); list.RemoveAll(item => item.Point[0] == 0 && item.Point[1] == 0); //去除重复数据 list = list.Distinct(new OlineUserComparer()).ToList(); return list; } public class NearUserComparer : IEqualityComparer { public bool Equals(NearRiderModel x, NearRiderModel y) { if (x == null) return y == null; return x.Name == y.Name; } public int GetHashCode(NearRiderModel obj) { if (obj == null) return 0; return obj.Name.GetHashCode(); } } public class OlineUserComparer : IEqualityComparer { public bool Equals(ReceiveMsgModel x, ReceiveMsgModel y) { if (x == null) return y == null; return x.MemberId == y.MemberId; } public int GetHashCode(ReceiveMsgModel obj) { if (obj == null) return 0; return obj.MemberId.GetHashCode(); } } } } }