Championship standings example

Posts: 287
OK, I understand, I don't really use the script, just 2 CSV with good format and dataset "STANDINGS" and dataorder "live championship position". I make test with all and think the script do something, but not in this case .... sorry
Posts: 287
Test again and now something work, because I don't create in my first test the all 4 custom data as need in script:
cds_pos / cds_name /cds_carnum / cds_points
// Check if there is a driver in the session who was NOT in the standings csv
if (!_standings.ContainsKey(result.Entity.Id))
{
// This driver isn't in the standings yet, let's add him
driver = new DriverContender();
driver.CustomerId = result.Entity.Id;
driver.Name = result.Entity.Name;
driver.CarNumber = result.Entity.Car.Number;
driver.ChampPoints = 0;
_standings.Add(driver.CustomerId, driver);
}
else
{
// Otherwise, grab him from memory
driver = _standings[result.Entity.Id];
}

In this code what happen to driver in CSV but not in session ? In my case they don't come with other
Posts: 287
private void UpdateSessionChampResults()
{
foreach (var driver in _standings.Values)
{
// If this driver is in the session, he has his Entity linked up
// If not, Entity is null
if (driver.Entity != null)
{
// update the ChampionshipResult object
var champ = driver.Entity.ChampionshipResult;

champ.Position = driver.ChampPosition; // previous pos
champ.LivePosition = driver.LiveChampPosition; // updated pos
champ.Points = driver.ChampPoints; // previous points
champ.LivePoints = driver.LiveChampPoints; // updated points
}
}
}


Or is it in this part that driver in CSV are deleted ?
Posts: 785
Sorry I have a hard time figuring out what you mean.

The code simply does these steps:

  1. LoadPointSystem: Load point structure from spreadsheet (how many points to award per position)
  2. LoadStandings: Load current standings from spreadsheet (e.g. which driver has how many points)
  3. UpdateSessionStandings: go through the drivers in the standings, check their current position and award them the points for this race.
  4. UpdateChampPositions: assign championship (live) position based on their points
  5. UpdateSessionChampResults: go through the drivers in the session and also assign the champ data to the Entity.ChampionshipResult data. This can be used in regular databinding, there should be bindings for each of these.
  6. UpdateDataSets: for each driver in the standings, add his championship data (pos, name, carnumber and points as an example) to a bunch of Custom Dataset items. This allows you to show a set of standings that include drivers that are not in your session, but this is a very "hacky" way to do it.

The logic is very simple: everyone that is in the session will be awarded points. Everyone that is not in the session, but is listed in your standings csv, will also be listed, but you cannot show them in any regular data sets because they are not in the session.


I feel that this is such a recurring issue that I will investigate if I can add this functionality to ATVO directly. It will probably not support all usecases especially with complicated point systems or bonus points etc, but I should manage some simple functionality.
Posts: 287
Thanks for this answer, if I understand with this code we supposed to see in a specific widget use custom data could show together pilot in session and pilot in csv.

As you know the code in exemple has some errors, so I try to make correction, now it is ok (no errors visible) but impossible to get together driver in and out in my widget.

So I put my correction and if you have time or if someone could test it it will be nice to say me what is wrong

using System;
using System.Data;
using ATVO.ThemesSDK;
using ATVO.ThemesSDK.Data.Entity;
using ATVO.ThemeEditor.ThemeModels;
using ATVO.ThemeEditor.Scripting.DotNET;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Scripts
{
public class championnat : IScript
{
private Dictionary<int, int> _pointSystem = new Dictionary<int, int>();
private Dictionary<int, DriverContender> _standings = new Dictionary<int, DriverContender>();

public object Execute(ThemeContentItem item, object value, string parameter, ISimulation sim)
{
if (value == null)
{
// do something appropriate, in this case probably just return nothing
return null;
}
// Make sure point system and standings are loaded
LoadPointSystem(item.Theme);
LoadStandings(item.Theme);

// Update the points
UpdateSessionStandings(sim);

// Sort by points and assign position
// This updates positions for drivers in the session AND drivers not in the session
UpdateChampPositions();

// Also update the champ results for drivers in the session
// in case you are showing these somewhere else (in another widget)
UpdateSessionChampResults();

// Finally update our Custom Data Sets so the widgets are showing the new results
UpdateDataSets(item.Theme);

return value.ToString();
}

private void UpdateSessionStandings(ISimulation sim)
{
// Loop through entity results in the session and update the standings
foreach (var result in sim.Session.Current.Results)
{
DriverContender driver;

// Check if there is a driver in the session who was NOT in the standings csv
if (!_standings.ContainsKey(result.Entity.Id))
{
// This driver isn't in the standings yet, let's add him
driver = new DriverContender();
driver.CustomerId = result.Entity.Id;
driver.ChampPosition = (1000-driver.ChampPoints);
driver.Name = result.Entity.Name;
driver.CarNumber = result.Entity.Car.Number;
driver.ChampPoints = 0;
// driver.Exist = "1";
_standings.Add(driver.CustomerId, driver);
}
else
{
// Otherwise, grab him from memory

driver = _standings[result.Entity.Id];
}

// Link him to the session entity
driver.Entity = result.Entity;

// Add the champ points obtained during this race
driver.LiveChampPoints = driver.ChampPoints + _pointSystem[result.Position]; // Or result.LivePosition to update during a lap
}
}

private void UpdateChampPositions()
{
// Sort the standings by live champ points and assign positions in order
var sorted = _standings.Values.OrderByDescending(d => d.LiveChampPoints);

int position = 1;
foreach (var driver in sorted)
{
driver.LiveChampPosition = position;
position += 1;
}
}

private void UpdateSessionChampResults()
{
foreach (var driver in _standings.Values)
{
// If this driver is in the session, he has his Entity linked up
// If not, Entity is null
if (driver.Entity != null)
{
// update the ChampionshipResult object
var champ = driver.Entity.ChampionshipResult;

champ.Position = driver.ChampPosition; // previous pos
champ.LivePosition = driver.LiveChampPosition; // updated pos
champ.Points = driver.ChampPoints; // previous points
champ.LivePoints = driver.LiveChampPoints; // updated points
}

}
}

private void UpdateDataSets(Theme theme)
{
// Assuming you have four Custom Data Set items:
var cds_pos = theme.CustomDataSets.Find("cds_pos"); // for champ position
var cds_name = theme.CustomDataSets.Find("cds_name"); // for driver name
var cds_carnum = theme.CustomDataSets.Find("cds_carnum"); // for car num
var cds_points = theme.CustomDataSets.Find("cds_points"); // for champ points

// Clear their data
cds_pos.Data.Clear();
cds_name.Data.Clear();
cds_carnum.Data.Clear();
cds_points.Data.Clear();

// Add the new data in order
foreach (var driver in _standings.Values.OrderBy(d => d.LiveChampPosition))
{
//var LiveChampPosition2 = LiveChampPosition.ToString();
cds_pos.Data.Add(new CustomDataSetItem(driver.LiveChampPosition.ToString()));
cds_name.Data.Add(new CustomDataSetItem(driver.Name));
cds_carnum.Data.Add(new CustomDataSetItem(driver.CarNumber));
cds_points.Data.Add(new CustomDataSetItem(driver.LiveChampPoints.ToString()));
}
}

private void LoadPointSystem(Theme theme)
{
if (_pointSystem.Count == 0)
{
// Read point system from an embedded spreadsheet
// Two columns: position, points
var sheet = theme.Spreadsheets.Find("points_system.csv");

foreach (var row in sheet.Table.Data.Rows.OfType<DataRow>())
{
var position = Convert.ToInt32(row[0]);
var points = Convert.ToInt32(row[1]);
_pointSystem.Add(position,points);
}
}
}

private void LoadStandings(Theme theme)
{
if (_standings.Count == 0)
{
// Read current standings from embedded csv
// Columns: customer_id, position, carnumber, lastname, firstname, points
var sheet = theme.Spreadsheets.Find("standings.csv");

foreach (var row in sheet.Table.Data.Rows.OfType<DataRow>())
{
var custid = Convert.ToInt32(row[0]);
var position = Convert.ToInt32(row[1]);
var carnum = Convert.ToString(row[2]);
var name = String.Concat(row[4], row[3]);
var points = Convert.ToInt32(row[5]);
// var exist = Convert.ToString(row[6]);

var driver = new DriverContender();
driver.CustomerId = custid;
driver.ChampPosition = position;
driver.CarNumber = carnum;
driver.Name = name;
driver.ChampPoints = points;
// driver.Exist = exist;

_standings.Add(custid,driver);
}
}
}
}

public class DriverContender
{
public IEntity Entity {get;set;}
public int CustomerId {get;set;}
public string CarNumber {get;set;}
public string Name {get;set;}
public int ChampPosition {get;set;}
public int ChampPoints {get;set;}
public int LiveChampPosition {get;set;}
// public string Exist {get;set;}
public int LiveChampPoints {get;set;}
}
}
Posts: 287
Impossible to edit my post
Don't look my post I do tests again. Some new things.

First the system don't work in multiclass session (i do Watch in iracing and search active race, so I don't focus on that before)

IT IS WORKING in single class race, I can saw pilot from session and pilot from CSV. New Pilot from session are correctly showing with good points, pilots in Session and in CSV are showing with good points (old & new added) and pilot only in CSV are showing with 0 point

I have to search a little bit more.
Posts: 29
Is there an example theme using this feature?
Posts: 287
Some more investigations. It is ok with MULTI too, just with TEAM session you have to change ID to Team ID in the CSV.

But always the same problem : driver not in session have 0 point even if they get points in CSV.
Posts: 287
Nick Thissen wrote:
It is assumed that you have widgets that have these custom datasets as their data set.

But to be honest: this code was a very rough example and should be done much better. Unfortunately I don't have much time today but I will see if I can add a better example soon.

Hi, Nick,
I've been very interrested if you can show me a better exemple with a better code ;)
Posts: 1
Hello Nick,

New user here. I am looking to add a live points tracker to my broadcast but the format is a little complicated as we use the current NASCAR playoffs format. Does this update/feature or any others that you have allow for tracking elimination style playoff rounds?

For example, we have 16 playoff drivers, 3 rounds. 6 drivers are eliminated after round 1, 6 more after round 2, leaving 4 drivers for the final playoff race. Our drivers are scored by position in the race plus with 1 bonus point for winning the pole, leading a lap, and finishing with 0 incident points. Is there any possible way to code an overlay for something like this? Basically I'm just looking to show a live points update in the corner of the broadcast that displays all drivers above the cutline and the 6 drivers currently below the cut line.
Thanks!
Posts: 72
Bumping this because we need a simpler explanation on what to do. Emmanuel's script works, but everything else isn't clear and concise. Does anyone have it working in their theme that they can share? Or share the proper steps to get it to work for both live points and pre-race points?
Posts: 72
Alright bumping this again, somehow I got it to half work but the live data only updates when the script is executed, so I need to set a constant timer to keep executing the script. I also need help on getting it to work with Heats and Qualifying to give points that way. Any help is appreciated!
Posts: 72
Josh Lee wrote:
Alright bumping this again, somehow I got it to half work but the live data only updates when the script is executed, so I need to set a constant timer to keep executing the script. I also need help on getting it to work with Heats and Qualifying to give points that way. Any help is appreciated!

Amendment: It updates every time past the start finish while also needing another script execute to work. This can become a problem for longer tracks where a lot of passing is happening and the points just aren't updating quick enough.
Posts: 12
I would really appreciate a step by step on how to get this working. TIA.