public RideProcessor(string userId) { _outputLock = new ReaderWriterLockSlim(); UserId = userId; // load the turbo _spotData = new Spot(); _lastSpotData = null; // Set-up the lease LeaseId = GenerateLease(12); // Set the initial timeout LastUpdateTimestamp = DateTime.UtcNow; _messageQueue = new Queue<InterfaceDatum>(QUEUE_CAPACITY); _queueLock = new ReaderWriterLockSlim(); _zeroingTimer = new Timer(CheckZeroing, null, 1000, 4000); Rider = Rider.LoadAny(userId); // will load either a real or virtual rider if (Rider != null) { Turbo = TurboTrainer.Load(UserId, Rider.CurrentTurbo, Rider.TurboIsCalibrated); } }
public Spot Copy() { Spot newSp = new Spot(); newSp.id = id; newSp.t = t; newSp.s = s; newSp.c = c; newSp.h = h; newSp.p = p; return newSp; }
private void ProcessMessage(InterfaceDatum p) { try { if (_outputLock.TryEnterWriteLock(OUTPUT_LOCK_TIMEOUT_MS)) { if (_lastMessage != null) { _lastSpotData = _spotData.Copy(); _spotData.id = UserId; _spotData.t = Utilities.DbTime.ToUnsignedDbTicks(DateTime.UtcNow); // heartrate is easy - just check its not a reset _spotData.h = p.h; // Speed if (p.wt > 0) { double deltaDistance = 0.000001 * (double)p.w * (double)Rider.BikeWheelSizeMm * Math.PI; _spotData.s = (float)(deltaDistance * 1024 * 3600 / (double)p.wt); // kmph } // Cadence if (p.pt > 0) { _spotData.c = (int)(60 * 1024 * (double)p.p / (double)p.pt); } // Power if (Rider.EstimatedPower && Turbo == null) { _spotData.p = 0; } // This condition will only estimate if we're not calibrating else if (Rider.EstimatedPower && _calibrationTimer == null) { _spotData.p = (int)Turbo.Power(_spotData.s); } else { if (p.ec > 0) { _spotData.p = (int)((float)p.e / (float)p.ec); if (_lastSpotData != null) { // Take a time average double dt = 0.001 * (double)(_spotData.t - _lastSpotData.t); float sf = (float)Math.Exp(-dt / 1.7); _spotData.p = (int)(sf * _lastSpotData.p + (1 - sf) * _spotData.p); } } else { _spotData.p = 0; } } // Are we calibrating - this if (_calibrationTimer != null) { Turbo.UpdateCalibrationData(this, _spotData); string message = Turbo.GetCalibrationMessage(); if (!string.IsNullOrEmpty(message)) { CycliManager.Instance.SendCalibrationMessage(UserId, message); } } } _lastMessage = p; } } catch (Exception ex) { Debug.WriteLine(ex.Message); } finally { _outputLock.ExitWriteLock(); } // Let the outside world know - this is outside the lock as // the race processor will try and access the updated data // within a read lock System.Diagnostics.Debug.WriteLine(string.Format("Ride Process:{0} {1} {2:N2} {3:N2}", _spotData.id, _spotData.t, _spotData.s, _spotData.p)); OnSpotData(); }
public void UpdateCalibrationData(RideProcessor rideProcessor, Spot spot) { _calibrationData.Add(spot.Copy()); }
public void SendSpotData(string userId, Spot spot) { try { _ConnectionProcessLock.EnterReadLock(); // Is the user connection string connectionId; if (_connections.TryGetValue(userId, out connectionId)) { Context.Clients.Client(connectionId).receiveSpotData(spot); } } finally { _ConnectionProcessLock.ExitReadLock(); } }
private void Start(object state) { // set the start time before releasing the race logging RaceStartTicks = Utilities.DbTime.ToUnsignedDbTicks(DateTime.UtcNow); // Enable the race for all - define initial positions int position = 1; try { _SpotLock.EnterWriteLock(); foreach (Race.Participant p in Race.Participants) { if (p.Status == @"Scheduled") { // Initial spot data Spot curSpot = new Spot(); curSpot.id = p.UserId; curSpot.t = RaceStartTicks; curSpot.s = 0; curSpot.c = 0; curSpot.h = 0; curSpot.p = 0; _Spots.Add(p.UserId, curSpot); } } } finally { _SpotLock.ExitWriteLock(); } try { _RaceSpotLock.EnterWriteLock(); foreach (Race.Participant p in Race.Participants) { /////////////// Need to revist this! if (p.Status == @"Scheduled") { // Initial Race data RaceSpot curRaceSpot = new RaceSpot(); curRaceSpot.id = p.UserId; curRaceSpot.d = 0; curRaceSpot.t = 0; curRaceSpot.s = 0; curRaceSpot.c = 0; curRaceSpot.k = 0; curRaceSpot.p = 0; curRaceSpot.e = 0; curRaceSpot.h = 0; curRaceSpot.b = 0; curRaceSpot.i = 0; curRaceSpot.v = 0; curRaceSpot.f = false; // not finished curRaceSpot.a = false; // not abandonned curRaceSpot.pos = position++; _RaceSpots.Add(p.UserId, curRaceSpot); _RaceSpotHistory.Add(p.UserId, new Stack<RaceSpot>()); // Need to clone here or the stack will just contain a reference to the original _RaceSpotHistory[p.UserId].Push(curRaceSpot.Copy()); } } // tell the db Race.Start(); } finally { _RaceSpotLock.ExitWriteLock(); } // Attach the race Processors CycliManager.Instance.AttachRiderProcessors(this, Race); // Start the race CycliManager.Instance.SendStartRace(Race); // Start the updater thread _UpdateRaceSpotTimer = new Timer(UpdateRaceSpotData, null, 0, 1000); }