Multiple Ranking not working properly [C#]

Hello, I’m trying to implement multiple ranking system, that takes in lapCount, waypointCount, waypointDistance.

Now my problem is that when I update the ranking, acording to lapCount etc. it sort of removes that ranking from other NPC’s.
Well it’s hard to explain… but as an example:

Lap 1,
RedCar Pos 1
BlueCar Pos 2
GreenCar pos 3

…now Red car reaches Lap 2, and this is what hapens:

Lap 2,
RedCar pos 1
BlueCar Pos 1
GreenCar pos 2

I’m not sure how to eliminate this.
But here is my ranking function:

	void CalcCarRankings()
	{
		for (int i=0; i< aiCar.Length; i++)
		{
			int curWaypoint = currentWaypoint[i];
			int curLap = carLap[i];
            int curRank = aiCar.Length; // take the total length of cars
			
			for (int j=0; j< aiCar.Length; j++)
			{
				
				// Check 1, Lap Check ( if arrayA Lap is larger than arrayB Lap, push back)				
				if (curLap > carLap[j]) 
				{
		        	curRank--;
				}
				// Check 2, Checpoint Check (if arrayA waypoint is larger than arrayB waypoint, push back)
				else if (curWaypoint > currentWaypoint[j]) 
				{
	        		curRank--;				
				}
				// Check 3, Checpoint Distance Check TODO...	
				
			}		
			carRank[i] = curRank;
			//carRank[i] = Mathf.Clamp(carRank[i],0,aiCar.Length);			
		}
	}

Anyone?

A different and easier to maintain solution (from my point of view) would be to make all cars comparable (IComparable). You need to implement the CompareTo method additionally and then you can just sort the array and you get the correct order.

Uhm could you show me an example? I looked over msdn and it shows that i have to make the class IComparable instead of MonoBehaviour.
I didnt know about IComparable.

You would have to implement the IComparable interface.

public class Car : MonoBehaviour, IComparable {
   public int CompareTo(object obj) {
        if (obj == null) return 1;

        Car otherCar = obj as Car;
        if (otherCar != null) 
            //do your comparisons here
        else 
           throw new ArgumentException("Object is not a Car");
    }
}

Easy Peasy!

Thanks, I allready did some tests, and IComparable didnt do the trick, but this aproach is a bit different, I’ll have a look at it and see if i can get it working.
To note out

My Scritp looks something like this at the moment:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

public class RaceManager : MonoBehaviour, IComparable
{
	public CarController[] aiCar;// lets test a vehicle		
	public GameObject waypointContainer;
	public int selectedCar;
	private List<Vector3> waypoints;
	public int[] currentWaypoint;
	public int[] carRank;
	public int[] carLap;
	
	public int CompareTo(object obj)
	{
		if (obj == null) return 1;

		CarController otherCar = obj as CarController;
		if (otherCar != null)
			//do your comparisons here			
		else
		   throw new ArgumentException("Object is not a Car");
	}
	
	void Start ()
	{		
		currentWaypoint = new int[aiCar.Length];	
		carRank = new int[aiCar.Length];
		carLap = new int[aiCar.Length];		
	}
}

As you can see I store lap’s, rankings in arrays, so that I can ask from this class, what one or another car does. I’ll start looking into IComparable now more

Well that’s because you put IComparable on the RaceManager rather than the CarController.
Put the IComparable on the CarController, implement the CompareTo there, and then you can use it like so:

List<CarController> cars = new List<CarController>();

void SomeMethod() {
   cars.Sort();
}

the comparison bit that was commented out for you to implement should probably look like:

public int CompareTo(object obj)
{
   if(obj == null) return 1;

   CarController otherCar = obj as CarController;
   if (otherCar != null) {
      int rankComparison = this.lap.CompareTo(otherCar.lap);
      if(rankComparison < 1) { // this car's lap was lower so compare waypoints
         rankComparison = this.waypoint.CompareTo(otherCar.waypoint);
      }
      return rankComparison;
   } else {
      throw new ArgumentException ("Object is not a CarController");
   }
}

Edit: Although you should really play with the comparison code. There could be weirdness if a car is down two laps or so, or I may have the logic backwards.

It seems like it’s getting really complycated, I dont want to believe that such a simple task needs so much modifications to the code.
Anyway I’m thinking of a different approach, I allready have the total length of my spline. Maybe I should Calculate current distance and then do some lap multiplyers?
For example:

MaxDistance = SplineLength * MaxLaps
TraveledDistance = CurrentSplineLength * CurrentLap
Precentage = TraveledDistance / MaxDistance

*note TraveledDistance will be multiplyed by current lap because it’s looping from 0 to final distance…

And then id Use My Array code implementation with Precentage to do rankings?
What may go wrong with this method?

It’s funny that The simplest task is so hard to nail properly. I got AI working yesterday and now I wasted my whole day trying to figure out how to do rankings

I think there was a small glitch in Democres pseudocode (line 8) in the last code sample. Another "simplification would be to use the generic IComparable interface. I removed the exception code, just to highlight what it would be about in the simplest (though incomplete) form:

public class Car : MonoBehaviour, IComparable <CarController> {
    public int CompareTo(CarController otherCar)
    {
      int rankComparison = this.lap.CompareTo(otherCar.lap);
      if(rankComparison == 0) { // Same lap, the waypoint decides
         rankComparison = this.waypoint.CompareTo(otherCar.waypoint);
      }
      return rankComparison;
    }
}