Pit and Chequered flag info

Posts: 11
Hi everybody,

I try to make showing pit and some infos on stading panel


I created standing and want to add infos. I put pit image to the standing panel and I added scripts which you can find under the message. How can I connect between code and image ? I want to show when driver pits in P image will appear. I don't know that code is correct. I just found on iRacing Forum and I also don't have any code knowledge :/

using System; 
using ATVO.ThemesSDK;
using ATVO.ThemesSDK.Data.Results;
using ATVO.ThemeEditor.ThemeModels;

namespace Scripts
{
public class Script
{

public object Execute(ThemeContentItem item, object value, string parameter, ISimulation sim)
{
IEntitySessionResult result = (IEntitySessionResult) value;

if (result.DidNotStart == true)
return "DNS";

if (result.Out == true)
return "DNF";

if (result.Entity.Car.Movement.IsInPits == true)
return "PIT";

if (result.Finished == true)
return "FIN";

else
    return "";
   
}
}
}


I hope I can find a solution for it :)

Kindly Regards,
Mertcan
Edited (1 time)
Posts: 785
The script will return a string (text) depending on several conditions. If the driver did not start it will say "DNS", if he disconnected it will say "DNF" and if he's in the pits it will say "PIT". Can you verify that this step at least works? To make this work you need to put a Label with a binding to "entitysessionresult_object" and this script selected as the converter script. If all is well the Label should show the correct text. If that is working you can remove this again, as you don't want to show the text.

The next step is showing an image based on the text. To do that you can use the Background of a Label (or SubWidget) and make it a Dynamic Image. Dynamic images take text as input and convert it to a filepath (relative to your theme folder) of an image. If you make images named "PIT.png", "DNF.png" etc, then you can refer to the images like this. In the Dynamic Image properties you need to add a binding to "entitysessionresult_object" just like in the text before, and select the script as the converter script. This time you need one more step which is the translation between this text ("PIT") and the image path (for example: "Images/status/PIT.png". You do this with the Path property, which takes a "template" path where the macro "{0}" will be replaced with your script output.

If your images are stored in a folder called "status" you can use this Path: "Images/status/{0}.png". The {0} is the macro and will be replaced with PIT,DNF,DNS, etc.
Posts: 11
I really thank you for your attention. I will change them :)
Posts: 9
Hi,

I modified my Overlay with a script like this one, but now i have the problem with the format of my output (livegap) and
i have no idea to change this format with the script. I hope anyone can help me.



using System; 
using ATVO.ThemesSDK;
using ATVO.ThemesSDK.Data.Results;
using ATVO.ThemeEditor.ThemeModels;

namespace Scripts
{
public class Script
{

public object Execute(ThemeContentItem item, object value, string parameter, ISimulation sim)
{
IEntitySessionResult result = (IEntitySessionResult) value;

if (result.DidNotStart == true)
return "OUT";

if (result.Out == true)
return "OUT";

if (result.Entity.Car.Movement.IsInPits == true)
return "IN PIT";

if (result.Finished == true)
return "FINISH";

if (result.Position == 1)
return "LAP " + result.CurrentLap.Number;

else
    return "+" + result.LiveGap;
   
}
}
}



BR Alex
Posts: 49
using System; 
using ATVO.ThemesSDK;
using ATVO.ThemesSDK.Data.Entity;
using ATVO.ThemeEditor.ThemeModels;
using ATVO.ThemeEditor.Controls;
using ATVO.ThemeEditor.Scripting.DotNET;
using ATVO.ThemesSDK.Data.Enums;
using ATVO.ThemesSDK.Data.Results;
namespace Scripts
{
public class Script : IScript
{
public object Execute(ThemeContentItem item, object value, string parameter, ISimulation sim)
{
// Bind to "entitysessionresult_obj" to get the IEntitySessionResult as the value

// Cast to IEntitySessionResult type
IEntitySessionResult result = (IEntitySessionResult) value;

// Check DNS, Out, Pits, etc
if (result == null)
return "";

if (result.DidNotStart)
return "DNS";

if (result.Out)
return "OUT";

if (result.Entity?.Car?.Movement?.IsInPits == true)
return "IN PITS";

if (result.Finished)
return "FIN";

// If none of these are true, then show the gap

// We need the following information to determine whether to show gap or laps
var pos = result.LivePosition;
var gap = result.LiveGap;
var laps = result.LiveGapLaps;
var type = result.Session.Type;

// Optional: there is no gap for P1 so show nothing
if (pos == 1)
return "";

// If car is lapped AND this is a race session,
// then show nr of gap laps instead of gap time
if (laps > 0 && type == SessionType.Race)
{
if (laps == 1)
return "1 Lap"; // to avoid incorrect "1 Laps"
else
return laps + " Laps";
}

// If the car is in the same lap just return the time
return gap.ToString("0.000");
}
}
}
Posts: 28
Hi All,

I've the script in the last post by Jason. Whilst functionally it works well, I have found that when used on a ticker, it gradually grinds ATVO to a halt. It becomes unusable until I reload the theme if I can, or I have to exit and restart ATVO.

Has anyone else had this problem?

Thanks,
Alex.
Posts: 49
I have a theme that uses it that has over 200 widgets that does not grind to a halt. It is used in several parts of the theme.
Posts: 785
Alex McKellar wrote:
Hi All,

I've the script in the last post by Jason.  Whilst functionally it works well, I have found that when used on a ticker, it gradually grinds ATVO to a halt.    It becomes unusable until I reload the theme if I can, or I have to exit and restart ATVO.

Has anyone else had this problem?

Thanks,
Alex.
Can you check with the script performance view whether it's really this script that's taking long? I can't imagine, nothing in that script should take any time at all. Note you have to enable the script benchmarking in the script properties I think.
Posts: 28
200 times....Damn!

I have found using it to do custom backgrounds is fine. But, using it to modify the data output is where I have issues. I don't think I made any modifications, but, I will go back to the drawing board and start with a single widget and work my way up.

I've had the script performance window up while running. I can't remember the values, but, it did seem to spike at times. Will do some more testing.

Thank you.
Posts: 9
Hello,
first thank you for your help in the last time.
But now i have a new problem with the format of my gaps, i hope you can help me again.
When the gap is more than 59.999 seconds i will have this format (00:00.000).
You can see my results in here:


and here is my code:
using System; 
using ATVO.ThemesSDK;
using ATVO.ThemesSDK.Data.Entity;
using ATVO.ThemeEditor.ThemeModels;
using ATVO.ThemeEditor.Controls;
using ATVO.ThemeEditor.Scripting.DotNET;
using ATVO.ThemesSDK.Data.Enums;
using ATVO.ThemesSDK.Data.Results;
namespace Scripts
{
public class status : IScript
{
public object Execute(ThemeContentItem item, object value, string parameter, ISimulation sim)
{
// Bind to "entitysessionresult_obj" to get the IEntitySessionResult as the value

// Cast to IEntitySessionResult type
IEntitySessionResult result = (IEntitySessionResult) value;

// We need the following information to determine whether to show gap or laps
var pos = result.LivePosition;
var gap = result.LiveGap;
var laps = result.LiveGapLaps;
var type = result.Session.Type;

// Check the session type is RACE
if (type == SessionType.Race)
{

// Check DNS, Out, Pits, etc
if (result == null)
return "";

if (result.Finished)
return "FINISHED";

if (result.DidNotStart)
return "OUT";

if (result.Out)
return "OUT";

if (result.Entity?.Car?.Movement?.IsInPits == true)
return "in Pit";



// If none of these are true, then show the gap

// Optional: there is no gap for P1 so show nothing
if (pos == 1)
return "LAP " + result.CurrentLap.Number;

// If car is lapped AND this is a race session,
// then show nr of gap laps instead of gap time
if (laps > 0 && type == SessionType.Race)
{
if (laps == 1)
return "+" + "1 Lap"; // to avoid incorrect "1 Laps"
else
return laps + "+" + " Laps";
}
// If the car is in the same lap just return the time
return "+" + gap.ToString("0.000");
}

// If the session type not RACE return LEADER for P1 and time for the rest
if (result == null)
return "no time";

if (pos == 1)
return "LEADER";

else
return "+" + gap.ToString("0.000");
}
}
}


BR Alex
This is what we use internally for custom themes to convert gaps:
internal static string ConvertToTimeString(this float seconds, string secFormat = "0.000", bool withMinutes = true, string prefix = "", string def = "")
{
if (seconds <= 0)
return def;

var min = 0;
float sectime;
if (withMinutes)
{
min = (int) (seconds / 60);
sectime = seconds % 60;
}
else
{
sectime = seconds;
}

var sb = new StringBuilder(prefix);
if (min > 0)
sb.Append(min).Append(':').Append(sectime.ToString("0" + secFormat));
else
sb.Append(sectime.ToString(secFormat));

return sb.ToString().Replace(',', '.');
}
Posts: 9
thanks for the fast answer, but I'm a noob in the scripting things.
at which position in the script i have to add this lines?

sorry for this stupid question...
Posts: 9
hello,
I hope anyone can help me with this script for the time format.
I have no idea there or how i have to use this code...

I'm an absolutly noob in this things.
Posts: 61
Simon Grossmann wrote:
This is what we use internally for custom themes to convert gaps:
internal static string ConvertToTimeString(this float seconds, string secFormat = "0.000", bool withMinutes = true, string prefix = "", string def = "")
{
    if (seconds <= 0)
        return def;

    var min = 0;
    float sectime;
    if (withMinutes)
    {
        min = (int) (seconds / 60);
        sectime = seconds % 60;
    }
    else
    {
        sectime = seconds;
    }

    var sb = new StringBuilder(prefix);
    if (min > 0)
        sb.Append(min).Append(':').Append(sectime.ToString("0" + secFormat));
    else
        sb.Append(sectime.ToString(secFormat));

    return sb.ToString().Replace(',', '.');
}

This is the exact same issue I ran into with the seconds on the same lap. Thank you Simon for this snippet of code. After some tweaks I got this working with the script shown above. Thank you for "guiding" me in some way :)

If somebody is interested, this is the part I changed:
From this:
// If the car is in the same lap just return the time
return "+" + interval.ToString("0.000");

To this:
// If the car is in the same lap just return the time
// If the car is in same lap but over a minute behind, convert total seconds to proper format
var min = 0;
float sectime;
if (interval > 60)
{
min = (int) (interval / 60);
sectime = interval % 60;
return "+" + min + ":" + sectime.ToString("00.000");
}
else
return "+" + interval.ToString("0.000");
Edited (1 time)
Posts: 56
Dwayne Prins wrote:
Simon Grossmann wrote:
This is what we use internally for custom themes to convert gaps:
internal static string ConvertToTimeString(this float seconds, string secFormat = "0.000", bool withMinutes = true, string prefix = "", string def = "")
{
    if (seconds <= 0)
        return def;

    var min = 0;
    float sectime;
    if (withMinutes)
    {
        min = (int) (seconds / 60);
        sectime = seconds % 60;
    }
    else
    {
        sectime = seconds;
    }

    var sb = new StringBuilder(prefix);
    if (min > 0)
        sb.Append(min).Append(':').Append(sectime.ToString("0" + secFormat));
    else
        sb.Append(sectime.ToString(secFormat));

    return sb.ToString().Replace(',', '.');
}

This is the exact same issue I ran into with the seconds on the same lap. Thank you Simon for this snippet of code. After some tweaks I got this working with the script shown above. Thank you for "guiding" me in some way :)

If somebody is interested, this is the part I changed:
From this:
// If the car is in the same lap just return the time
return "+" + interval.ToString("0.000");

To this:
// If the car is in the same lap just return the time
// If the car is in same lap but over a minute behind, convert total seconds to proper format
var min = 0;
float sectime;
if (interval > 60)
{
min = (int) (interval / 60);
        sectime = interval % 60;
        return "+" + min + ":" + sectime.ToString("00.000");
}
else
return "+" + interval.ToString("0.000");


But in this code "interval" is not defined, doesn't work
Posts: 61

But in this code "interval" is not defined, doesn't work

This is just a part of the code that is shown. Use the code provided at the beginning of this thread.
Posts: 56
Alexander Kroll wrote:
Hello,
first thank you for your help in the last time.
But now i have a new problem with the format of my gaps, i hope you can help me again.
When the gap is more than 59.999 seconds i will have this format (00:00.000).
You can see my results in here:


and here is my code:
using System; 
using ATVO.ThemesSDK;
using ATVO.ThemesSDK.Data.Entity;
using ATVO.ThemeEditor.ThemeModels;
using ATVO.ThemeEditor.Controls;
using ATVO.ThemeEditor.Scripting.DotNET;
using ATVO.ThemesSDK.Data.Enums;
using ATVO.ThemesSDK.Data.Results;
namespace Scripts
{
public class status : IScript
{
public object Execute(ThemeContentItem item, object value, string parameter, ISimulation sim)
{
// Bind to "entitysessionresult_obj" to get the IEntitySessionResult as the value

// Cast to IEntitySessionResult type
IEntitySessionResult result = (IEntitySessionResult) value;

// We need the following information to determine whether to show gap or laps
var pos = result.LivePosition;
var gap = result.LiveGap;
var laps = result.LiveGapLaps;
var type = result.Session.Type;

// Check the session type is RACE
if (type == SessionType.Race)
{

// Check DNS, Out, Pits, etc
if (result == null)
return "";

if (result.Finished)
return "FINISHED";

if (result.DidNotStart)
return "OUT";

if (result.Out)
return "OUT";

if (result.Entity?.Car?.Movement?.IsInPits == true)
return "in Pit";



// If none of these are true, then show the gap

// Optional: there is no gap for P1 so show nothing
if (pos == 1)
return "LAP " + result.CurrentLap.Number;

// If car is lapped AND this is a race session,
// then show nr of gap laps instead of gap time
if (laps > 0 && type == SessionType.Race)
{
if (laps == 1)
return "+" + "1 Lap"; // to avoid incorrect "1 Laps"
else
return laps + "+" + " Laps";
}
// If the car is in the same lap just return the time
return "+" + gap.ToString("0.000");
}

// If the session type not RACE return LEADER for P1 and time for the rest
if (result == null)
return "no time";

if (pos == 1)
return "LEADER";

else
return "+" + gap.ToString("0.000");
}
}
}


BR Alex

I have the same problem, the times I get are in seconds format (ex: 84,384)

I'm using this code provided by Simon to convert:

internal static string ConvertToTimeString(this float seconds, string secFormat = "0.000", bool withMinutes = true, string prefix = "", string def = "")
{
if (seconds <= 0)
return def;

var min = 0;
float sectime;
if (withMinutes)
{
min = (int) (seconds / 60);
sectime = seconds % 60;
}
else
{
sectime = seconds;
}

var sb = new StringBuilder(prefix);
if (min > 0)
sb.Append(min).Append(':').Append(sectime.ToString("0" + secFormat));
else
sb.Append(sectime.ToString(secFormat));

return sb.ToString().Replace(',', '.');

But the theme editor shows errors in the compilation like "Extension method must be defined in a non-generic static class".

I know you are too busy to act as teachers, but I cannot understand how it works and why it gives an error when you are supposed to use it constantly.

Thanks in advance for your help.
Posts: 785
The code won't just magically work if you copy/paste it, Simon posted that so you can see the logic we are using to convert "total seconds" (e.g. 84.384" into a laptime-like format (1:24.384).

The logic is pretty simple: we divide the total seconds by 60 and round down, and that gives the number of minutes:
min = (int) (seconds / 60);


Then we get the remainder of that division which gives the number of remaining seconds:
sectime = seconds % 60;


Then we just concatenate the whole thing together:
var sb = new StringBuilder(prefix);
if (min > 0)
sb.Append(min).Append(':').Append(sectime.ToString("0" + secFormat));
else
sb.Append(sectime.ToString(secFormat));


These parts you can almost copy/paste. The rest is just some logic to deal with different situations (sometimes we want the time with minutes, sometimes without, sometimes we want it positive, then negative, etc.)
Posts: 56
Could this work?

var tiempo = result.FastestLapTime;

public String CalcularTiempo(Int32 tiempo)
{
Int32 horas = (tiempo / 3600);
    Int32 minutos = ((tiempo-horas*3600)/60);
    Int32 segundos = tiempo-(horas*3600+minutos*60);
    return minutos.ToString() + ":" + segundos.ToString();

}

}

Edited (2 times)
Posts: 287
Hi, I don't know if problem come from last iRacing update, but pilots stop in pit return OUT and some of theme stay OUT until they drive !!!
Anyone see that too ?
Posts: 287
I made a test and place control OUT in bottum of the list check in my script, and now if a driver is OUT it show me PITS !!
if (result == null && type == SessionType.Race)
return "";

if (result.Entity?.Car?.Movement?.IsInPits == true && type == SessionType.Race)
return "PITS";

if (result.DidNotStart && type == SessionType.Race)
return "DNS";


if (result.Finished && type == SessionType.Race)
return "FINISH";


if (result.Out && type == SessionType.Race)
return "OUT";