Beispiel #1
0
        public override void Evaluate(RaceSpot myRs, RaceSpot[] rs)
        {
            Likelihood = 0;
            double thisProgress = _Race.RaceType.PercentComplete(myRs);
            double deltaProgress = thisProgress - _LastProgress;
            // This is a proactive tactic, so we same the likelihood

            double l = GetLikelihood(myRs);
            double scaledLikelihood = l * (1.0 - Math.Exp(-AGGRESSIVE_ATTACKS_PER_RACE * 0.04 * deltaProgress));
            // Use the score as a monte-carlo distribution
            if (_Rnd.NextDouble() < scaledLikelihood)
            {

                    // Am I in any sort of group and is that group going at less than my 5 minute pace
                double breakSpeed = TurboTrainer.PowerNormalisedSpeed(_Motor.PowerBands[1]);
                if (InGroup(myRs, rs) && myRs.s > 0 && myRs.s < breakSpeed)
                {
                    // initial target speed = 15-30% of existing speed
                    // Target break - between 30 secs and 2.5 minutes
                    _StopTime = myRs.t + 30000 + (ulong)(120000 * _Rnd.NextDouble());
                    RequestedPower = _Motor.PowerBands[1];      // Break at 5 minute
                    Likelihood = l;
                }
            }
            _LastProgress = thisProgress;
        }
Beispiel #2
0
 protected RaceSpot GroupLeader(RaceSpot myRs, RaceSpot[] rs)
 {
     RaceSpot leader = rs.Where(p => !p.f && !p.a && (p.d - myRs.d) > 0 && (p.d - myRs.d) < GROUP_DISTANCE_MTR).OrderByDescending(p => p.d).FirstOrDefault();
     return leader;
 }
Beispiel #3
0
        protected double GetLikelihood(RaceSpot rs)
        {
            double likelihood = 0;
            if (_LikelihoodPoints.Count > 0)
            {

                double pcnt = _Race.RaceType.PercentComplete(rs);
                // Find two points that surround this percentage
                TacticPoint before = _LikelihoodPoints.Where(p => p.PercentCompleted <= pcnt).OrderBy(p => p.PercentCompleted).LastOrDefault();
                TacticPoint after = _LikelihoodPoints.Where(p => p.PercentCompleted > pcnt).OrderBy(p => p.PercentCompleted).FirstOrDefault();
                if (after == null)
                {
                    likelihood = before.Value;
                }
                else
                {
                    double denom = (after.PercentCompleted - before.PercentCompleted);
                    double s = 0.5;
                    if (denom > 0.0)
                    {
                        s = (pcnt - before.PercentCompleted) * after.Value / denom;
                    }
                    likelihood = (1 - s) * before.Value + s * after.Value;
                }
            }
            return likelihood;
        }
Beispiel #4
0
 public abstract void Update(RaceSpot myRs, RaceSpot[] rs);
Beispiel #5
0
        private void ChooseTactic(RaceSpot myRs, RaceSpot[] rs)
        {
            double maxLikelihood = 0;
             _CurrentTacticIdx = 0; // Default time trial tactic
             for (int idx = 0; idx < _TacticsCompendium.Count; idx++)
             {
               _TacticsCompendium[idx].Evaluate(myRs, rs);

               if (_TacticsCompendium[idx].Likelihood > maxLikelihood)
               {
             maxLikelihood = _TacticsCompendium[idx].Likelihood;
             _CurrentTacticIdx = idx;
               }
             }
             _ReviewTacticsTime = _TacticsCompendium[_CurrentTacticIdx].ReviewTime();
        }
Beispiel #6
0
 public override void Update(RaceSpot myRs, RaceSpot[] rs)
 {
     if (myRs.t > _StopTime)
     {
         // I'm knackered - call it off;
         Likelihood = 0;
     }
 }
Beispiel #7
0
 public override void Update(RaceSpot myRs, RaceSpot[] rs)
 {
     // I'm in the lead!
     if (rs[0].id == _UserId)
     {
         Likelihood = 0;    // Force cancellation
     }
 }
Beispiel #8
0
 public override void Update(RaceSpot myRs, RaceSpot[] rs)
 {
     // Nothing to do here
 }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        public override void Evaluate(RaceSpot myRs, RaceSpot[] rs)
        {
            Likelihood = 0;    // Do not use unless it's going to work
            int chasedIdx = 0;
            while (rs[chasedIdx].id != _UserId && Likelihood == 0 && chasedIdx < rs.Length) // Last condition shouldn't be needed but is a backstop
            {
                if (!rs[chasedIdx].f && !rs[chasedIdx].a)
                {
                    // Only go throgh the chase routine if the lead rider is outside the drafting region
                    double gap = rs[chasedIdx].d - myRs.d;
                    if (gap > GROUP_DISTANCE_MTR)
                    {
                        double speedDiff = myRs.s - rs[chasedIdx].s;
                        double speedDiffMPerSec = speedDiff * RaceType.KMPH_TO_M_PER_SEC;
                        double timeToFinish = _Race.RaceType.EstimatedTimeToFinish(rs[chasedIdx], rs[chasedIdx].s);
                        // Are we going to catch them anyway?
                        if (speedDiffMPerSec * timeToFinish < gap)
                        {
                            // No we're not - do something about it!
                            if (timeToFinish > 0)
                            {

                                double[] powers = _Motor.AvailablePower();
                                int bandIdx = _Motor.AlphaBands.Select(alpha => timeToFinish <= alpha).Count(p => p) - 1;
                                if (bandIdx < 0)
                                {
                                    // Longer than 1 hour - scale the power
                                    RequestedPower = _Motor.RecoverPower + _Motor.AlphaBands[0] * (powers[0] - _Motor.RecoverPower) / timeToFinish;
                                }
                                else
                                {
                                    RequestedPower = powers[bandIdx];
                                }

                                // What speed will this give?
                                double maxSpeed = TurboTrainer.PowerNormalisedSpeed(RequestedPower);
                                double maxSpeedMPerSec = (maxSpeed - rs[chasedIdx].s) * RaceType.KMPH_TO_M_PER_SEC;
                                // Will this catch them?
                                if (speedDiffMPerSec * timeToFinish >= gap)
                                    // Yes!  Give it a go then
                                    Likelihood = GetLikelihood(myRs);
                            }
                        }

                    }
                }
                chasedIdx++;
            }
        }
Beispiel #11
0
 private int GetTargetValue(Race race, RaceSpot rs)
 {
     int v = int.MinValue;
     float x = (float)this.Race.RaceType.PercentComplete(rs);
     // scan the profile until we find the between
     float y = _RaceProfile.GetYValue(x);
     if (!float.IsNaN(y))
     {
         v = race.ProfileMin + (int)(0.01 * (float)(race.ProfileMax - race.ProfileMin) * y);
     }
     return v;
 }
Beispiel #12
0
        public RaceSpot Copy()
        {
            RaceSpot newrs = new RaceSpot();
              newrs.id = id;
              newrs.pos = pos;
              newrs.pom = pom;
              newrs.d = d;
              newrs.t = t;
              newrs.s = s;
              newrs.g = g;
              newrs.c = c;
              newrs.h = h;
              newrs.p = p;
              newrs.e = e;
              newrs.i = i;
              newrs.v = v;
              newrs.f = f;
              newrs.a = a;
              newrs.dp = dp;

              return newrs;
        }
Beispiel #13
0
        private double ExecuteTactics(RaceSpot myRs, RaceSpot[] rs)
        {
            DateTime timeNow = DateTime.UtcNow;
             if (_CurrentTacticIdx < 0 ||_ReviewTacticsTime < timeNow)
             {
               // Time to review
               ChooseTactic(myRs, rs);
             }
             else
             {
               _TacticsCompendium[_CurrentTacticIdx].Update(myRs, rs);
               // Some condition has been met in a simple update that forces a full review
               if (_TacticsCompendium[_CurrentTacticIdx].Likelihood < 0.05)  // We really should be looking again at this score
               {
            ChooseTactic(myRs, rs);
               }
             }
             System.Diagnostics.Debug.WriteLine(string.Format("Virtual {0}  {1}  {2}   {3}   {4}   {5}",
             myRs.t,
             this.UserName,
               myRs.pos,
               _TacticsCompendium[_CurrentTacticIdx].TacticName,
               _TacticsCompendium[_CurrentTacticIdx].RequestedPower,
               _Motor.Tank()));

             return _TacticsCompendium[_CurrentTacticIdx].RequestedPower;
        }
Beispiel #14
0
 protected bool InGroup(RaceSpot myRs, RaceSpot[] rs)
 {
     // Are we in a group to break out?
     int inGroup = 0;
     foreach (RaceSpot r in rs)
     {
         if (Math.Abs(r.d - myRs.d) <= 10)
         {
             inGroup++;
         }
     }
     return (inGroup >= 2);
 }
Beispiel #15
0
 public override void Update(RaceSpot myRs, RaceSpot[] rs)
 {
     throw new NotImplementedException();
 }
Beispiel #16
0
 public override void Evaluate(RaceSpot myRs, RaceSpot[] rs)
 {
     // Look at the available power band speeds to estimate
     double[] powers = _Motor.AvailablePower();
     double[] speeds = powers.Select(p => TurboTrainer.PowerNormalisedSpeed(p)).ToArray();
     double[] timesToFinish = speeds.Select(s => _Race.RaceType.EstimatedTimeToFinish(myRs, s)).ToArray();
     int bandIdx = _Motor.AlphaBands.Zip(timesToFinish, (alpha, t) => t <= alpha).Count(p => p)-1;
     for (int j = 0; j < timesToFinish.Length; j++)
     {
         System.Diagnostics.Debug.WriteLine(string.Format("Timetrialing time to finish {0}  {1:N2}    {2:N2}   {3:N2}     {4:N2}", myRs.id, _Motor.AlphaBands[j], powers[j], speeds[j], timesToFinish[j]));
     }
     System.Diagnostics.Debug.WriteLine(string.Format("Timetrialing power index {0}   {1} ", myRs.id, bandIdx));
     double timeToFinish = timesToFinish[0];
     if (bandIdx < 0)
     {
         // Longer than 1 hour - scale the power
         RequestedPower = _Motor.RecoverPower + _Motor.AlphaBands[0] * (powers[0] -_Motor.RecoverPower)  / timesToFinish[0];
     }
     else
     {
         timeToFinish = timesToFinish[bandIdx];
         RequestedPower = powers[bandIdx];
     }
     if (timeToFinish < _goTime)
     {
         Likelihood = 1.0;    // Force the final sprint
     }
     else
     {
         Likelihood = 0.1;  // Low score - this is the default
     }
 }
Beispiel #17
0
 public override void Evaluate(RaceSpot myRs, RaceSpot[] rs)
 {
     RequestedPower = _Motor.RecoverPower;
     // Lowest likelihood
     Likelihood = 0.1;
 }
Beispiel #18
0
        public override void Evaluate(RaceSpot myRs, RaceSpot[] rs)
        {
            // Nothing to do here - wheelsucking is an update by update action
            Likelihood = 0.0;
            RaceSpot hasLeader = GroupLeader(myRs, rs);
            if (hasLeader != null)
            {
                // What's my optimum power
                double leaderSpeed = hasLeader.s;
                double leaderPower = TurboTrainer.StandardPower(leaderSpeed);
                // For wheel sucking - only consider using 1hr power unless we're in the last 5 minutes
                // Use the leader speed to judge
                double timeToFinish = _Race.RaceType.EstimatedTimeToFinish(myRs, leaderSpeed);

                double[] powers = _Motor.AvailablePower();
                double optimalPower = 0;
                int bandIdx = _Motor.AlphaBands.Select(alpha => timeToFinish <= alpha).Count(p => p) - 1;
                if (bandIdx < 0)
                {
                    // Longer than 1 hour - scale the power
                    RequestedPower = _Motor.RecoverPower + _Motor.AlphaBands[0] * (powers[0] - _Motor.RecoverPower) / timeToFinish;
                }
                else
                {
                    optimalPower = powers[bandIdx];
                }
                // Not 1.0 as we may need to go for a sprint, or be condering a break
                double wheelsuckPower = WHEELSUCK_POWER_FRAC * leaderPower;
                if (wheelsuckPower <= optimalPower)
                {
                    // An aggressive rider be
                    // (a) less likely to wheel suck
                    Likelihood = (1 - _Aggression);
                    // (b) break earlier
                    if (timeToFinish < _offTime)
                    {
                        Likelihood = 0;
                    }
                    RequestedPower = wheelsuckPower;
                    _leader = hasLeader;
                }
            }
        }
Beispiel #19
0
 public override void Update(RaceSpot myRs, RaceSpot[] rs)
 {
     // Not used
 }
Beispiel #20
0
 public override void Update(RaceSpot myRs, RaceSpot[] rs)
 {
     if (_leader != null)
     {
         double leaderPower = TurboTrainer.StandardPower(_leader.s);
         RequestedPower = WHEELSUCK_POWER_FRAC * leaderPower;
     }
 }
Beispiel #21
0
 /// <summary>
 /// </summary>
 /// <param name="rs"></param>
 /// <returns></returns>
 public abstract void Evaluate(RaceSpot myRs, RaceSpot[] rs);
Beispiel #22
0
 public void SendLeaderboard(string raceId, RaceSpot[] rs)
 {
     try
       {
     _ConnectionProcessLock.EnterReadLock();
     // Is the user connection
     foreach (RaceSpot r in rs)
     {
       string connectionId;
       if (_connections.TryGetValue(r.id, out connectionId))
       {
     Context.Clients.Client(connectionId).receiveLeaderboard(raceId, rs);
       }
     }
       }
       finally
       {
     _ConnectionProcessLock.ExitReadLock();
       }
 }
Beispiel #23
0
        public void Finish(RaceSpot[] rss, Dictionary<string, Stack<RaceSpot>> history)
        {
            string sqlRiderUpdate = @"update cycli_race_riders set Position=@p, Distance=@d, Time=@t, Energy=@e, PedalStrokes=@k, Heartbeats=@b, TSS=@i " +
            "where RaceId=@r and UserId=@u";
            string sqlRaceUpdate = @"update cycli_races set Status='Finished' " +
              "where RaceId=@r and Status='Started'";

            SQLiteDatabase db = new SQLiteDatabase(true);
            try
            {
                db.ExecuteNonQuery(sqlRaceUpdate, "@r", this.RaceId);
                foreach (RaceSpot rs in rss)
                {
                    db.ExecuteNonQuery(sqlRiderUpdate, "@p", rs.pos, "@d", rs.d, "@t", rs.t, "@e", (int)rs.e, "@k", (int)rs.k, "@b", (int)rs.b, "@i", (int)rs.i, "@r", this.RaceId, "@u", rs.id);
                }
                db.CommitTransaction();
            }
            catch (Exception ex)
            {
                try
                {
                    db.RollbackTransaction();
                }
                catch (Exception ex1)
                {
                }
            }
            finally
            {
                // Don't need to close on a transaction
            }
            // Do points as a separate transaction
            string raceSpotSql = @"insert into cycli_race_spots (UserId, RaceId, Time, Distance, Speed, Cadence, HR, Power) " +
                            "values (@u, @r, @t, @d, @s, @c, @h, @p)";

            db = new SQLiteDatabase(true);
            try
            {
                foreach (string userId in history.Keys)
                {
                    Stack<RaceSpot> userHistory = history[userId];
                    foreach (RaceSpot rs in userHistory)
                    {
                        db.ExecuteNonQuery(raceSpotSql, "@r", this.RaceId, "@u", userId, "@t", rs.t, "@d", rs.d, "@s", rs.s, "@c", rs.c, "@h", rs.h, "@p", rs.p);
                    }
                }
                db.CommitTransaction();
            }
            catch (Exception ex)
            {
                try
                {
                    db.RollbackTransaction();
                }
                catch (Exception ex1)
                {
                }
            }
            finally
            {
            }
            // Mark the race as Finished
            this.Status = @"Finished";
        }