Added tools to make it easier to create a good PDF
@@ -0,0 +1,193 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : ConfigurationTool.cs
|
||||
/// Brief : Class that contains all the methods needed to create a config file for the OCR
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Tesseract;
|
||||
using System.IO;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class ConfigurationTool
|
||||
{
|
||||
public Zone MainZone;
|
||||
public const int NUMBER_OF_DRIVERS = 20;
|
||||
public const int NUMBER_OF_ZONES = 9;
|
||||
public const string CONFIGS_FOLDER_NAME = "./Presets/";
|
||||
|
||||
public ConfigurationTool(Bitmap fullImage, Rectangle mainZoneDimensions)
|
||||
{
|
||||
MainZone = new Zone(fullImage, mainZoneDimensions,"Main");
|
||||
AutoCalibrate();
|
||||
}
|
||||
public void ResetMainZone()
|
||||
{
|
||||
MainZone.ResetZones();
|
||||
}
|
||||
public void ResetWindows()
|
||||
{
|
||||
MainZone.ResetWindows();
|
||||
}
|
||||
public void SaveToJson(List<string> drivers, string configName)
|
||||
{
|
||||
string JSON = "";
|
||||
|
||||
JSON += "{" + Environment.NewLine;
|
||||
JSON += MainZone.ToJSON() + "," + Environment.NewLine;
|
||||
JSON += "\"Drivers\":[" + Environment.NewLine;
|
||||
|
||||
for (int i = 0; i < drivers.Count; i++)
|
||||
{
|
||||
JSON += "\"" + drivers[i] + "\"";
|
||||
if (i < drivers.Count - 1)
|
||||
JSON += ",";
|
||||
JSON += Environment.NewLine;
|
||||
}
|
||||
|
||||
JSON += "]" + Environment.NewLine;
|
||||
|
||||
JSON += "}";
|
||||
|
||||
if (!Directory.Exists(CONFIGS_FOLDER_NAME))
|
||||
Directory.CreateDirectory(CONFIGS_FOLDER_NAME);
|
||||
|
||||
string path = CONFIGS_FOLDER_NAME + configName;
|
||||
|
||||
if (File.Exists(path + ".json"))
|
||||
{
|
||||
//We need to create a new name
|
||||
int count = 2;
|
||||
while (File.Exists(path + "_" + count + ".json"))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
path += "_" + count + ".json";
|
||||
}
|
||||
else
|
||||
{
|
||||
path += ".json";
|
||||
}
|
||||
|
||||
File.WriteAllText(path, JSON);
|
||||
}
|
||||
public void AddWindows(List<Rectangle> rectangles)
|
||||
{
|
||||
foreach (Zone driverZone in MainZone.Zones)
|
||||
{
|
||||
Bitmap zoneImage = driverZone.ZoneImage;
|
||||
|
||||
for (int i = 1; i <= rectangles.Count; i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
//First zone should be the driver's Position
|
||||
driverZone.AddWindow(new DriverPositionWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 2:
|
||||
//First zone should be the Gap to leader
|
||||
driverZone.AddWindow(new DriverGapToLeaderWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 3:
|
||||
//First zone should be the driver's Lap Time
|
||||
driverZone.AddWindow(new DriverLapTimeWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 4:
|
||||
//First zone should be the driver's DRS status
|
||||
driverZone.AddWindow(new DriverDrsWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 5:
|
||||
//First zone should be the driver's Tyre's informations
|
||||
driverZone.AddWindow(new DriverTyresWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 6:
|
||||
//First zone should be the driver's Name
|
||||
driverZone.AddWindow(new DriverNameWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 7:
|
||||
//First zone should be the driver's First Sector
|
||||
driverZone.AddWindow(new DriverSectorWindow(driverZone.ZoneImage, rectangles[i - 1], 1, false));
|
||||
break;
|
||||
case 8:
|
||||
//First zone should be the driver's Second Sector
|
||||
driverZone.AddWindow(new DriverSectorWindow(driverZone.ZoneImage, rectangles[i - 1], 2, false));
|
||||
break;
|
||||
case 9:
|
||||
//First zone should be the driver's Position Sector
|
||||
driverZone.AddWindow(new DriverSectorWindow(driverZone.ZoneImage, rectangles[i - 1], 3, false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public void AutoCalibrate()
|
||||
{
|
||||
List<Rectangle> detectedText = new List<Rectangle>();
|
||||
List<Zone> zones = new List<Zone>();
|
||||
|
||||
TesseractEngine engine = new TesseractEngine(Window.TESS_DATA_FOLDER.FullName, "eng", EngineMode.Default);
|
||||
Image image = MainZone.ZoneImage;
|
||||
var tessImage = Pix.LoadFromMemory(Window.ImageToByte(image));
|
||||
|
||||
Page page = engine.Process(tessImage);
|
||||
using (var iter = page.GetIterator())
|
||||
{
|
||||
iter.Begin();
|
||||
do
|
||||
{
|
||||
Rect boundingBox;
|
||||
if (iter.TryGetBoundingBox(PageIteratorLevel.Word, out boundingBox))
|
||||
{
|
||||
//var text = iter.GetText(PageIteratorLevel.Word).ToUpper();
|
||||
//We remove all the rectangles that are definitely too big
|
||||
if (boundingBox.Height < image.Height / NUMBER_OF_DRIVERS)
|
||||
{
|
||||
//Now we add a filter to only get the boxes in the right because they are much more reliable in size
|
||||
if (boundingBox.X1 > image.Width / 2)
|
||||
{
|
||||
//Now we check if an other square box has been found roughly in the same y axis
|
||||
bool match = false;
|
||||
//The tolerance is roughly half the size that a window will be
|
||||
int tolerance = (image.Height / NUMBER_OF_DRIVERS) / 2;
|
||||
|
||||
foreach (Rectangle rect in detectedText)
|
||||
{
|
||||
if (rect.Y > boundingBox.Y1 - tolerance && rect.Y < boundingBox.Y1 + tolerance)
|
||||
{
|
||||
//There already is a rectangle in this line
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
//if nothing matched we can add it
|
||||
if (!match)
|
||||
detectedText.Add(new Rectangle(boundingBox.X1, boundingBox.Y1, boundingBox.Width, boundingBox.Height));
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (iter.Next(PageIteratorLevel.Word));
|
||||
}
|
||||
//DEBUG
|
||||
int i = 1;
|
||||
foreach (Rectangle Rectangle in detectedText)
|
||||
{
|
||||
Rectangle windowRectangle;
|
||||
Size windowSize = new Size(image.Width, image.Height / NUMBER_OF_DRIVERS);
|
||||
Point windowLocation = new Point(0, (Rectangle.Y + Rectangle.Height / 2) - windowSize.Height / 2);
|
||||
windowRectangle = new Rectangle(windowLocation, windowSize);
|
||||
//We add the driver zones
|
||||
Zone driverZone = new Zone(MainZone.ZoneImage, windowRectangle, "DriverZone");
|
||||
MainZone.AddZone(driverZone);
|
||||
|
||||
driverZone.ZoneImage.Save("Driver" + i+".png");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverData.cs
|
||||
/// Brief : Class used to store Driver informations
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class DriverData
|
||||
{
|
||||
public bool DRS; //True = Drs is opened
|
||||
public int GapToLeader; //In ms
|
||||
public int LapTime; //In ms
|
||||
public string Name; //Ex: LECLERC
|
||||
public int Position; //Ex: 1
|
||||
public int Sector1; //in ms
|
||||
public int Sector2; //in ms
|
||||
public int Sector3; //in ms
|
||||
public Tyre CurrentTyre;//Ex Soft 11 laps
|
||||
|
||||
public DriverData(bool dRS, int gapToLeader, int lapTime, string name, int position, int sector1, int sector2, int sector3, Tyre tyre)
|
||||
{
|
||||
DRS = dRS;
|
||||
GapToLeader = gapToLeader;
|
||||
LapTime = lapTime;
|
||||
Name = name;
|
||||
Position = position;
|
||||
Sector1 = sector1;
|
||||
Sector2 = sector2;
|
||||
Sector3 = sector3;
|
||||
CurrentTyre = tyre;
|
||||
}
|
||||
public DriverData()
|
||||
{
|
||||
DRS = false;
|
||||
GapToLeader = -1;
|
||||
LapTime = -1;
|
||||
Name = "Unknown";
|
||||
Position = -1;
|
||||
Sector1 = -1;
|
||||
Sector2 = -1;
|
||||
Sector3 = -1;
|
||||
CurrentTyre = new Tyre(Tyre.Type.Undefined, -1);
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that displays all the data found in a string
|
||||
/// </summary>
|
||||
/// <returns>string containing all the driver datas</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
string result = "";
|
||||
|
||||
//Position
|
||||
result += "Position : " + Position + Environment.NewLine;
|
||||
//Gap
|
||||
result += "GapToLeader : " + Reader.ConvertMsToTime(GapToLeader) + Environment.NewLine;
|
||||
//LapTime
|
||||
result += "LapTime : " + Reader.ConvertMsToTime(LapTime) + Environment.NewLine;
|
||||
//DRS
|
||||
result += "DRS : " + DRS + Environment.NewLine;
|
||||
//Tyres
|
||||
result += "Uses " + CurrentTyre.Coumpound + " tyre " + CurrentTyre.NumberOfLaps + " laps old" + Environment.NewLine;
|
||||
//Name
|
||||
result += "DriverName : " + Name + Environment.NewLine;
|
||||
//Sector 1
|
||||
result += "Sector1 : " + Reader.ConvertMsToTime(Sector1) + Environment.NewLine;
|
||||
//Sector 1
|
||||
result += "Sector2 : " + Reader.ConvertMsToTime(Sector2) + Environment.NewLine;
|
||||
//Sector 1
|
||||
result += "Sector3 : " + Reader.ConvertMsToTime(Sector3) + Environment.NewLine;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
//Structure to store tyres infos
|
||||
public struct Tyre
|
||||
{
|
||||
//If new tyres were to be added you will have to need to change this enum
|
||||
public enum Type
|
||||
{
|
||||
Soft,
|
||||
Medium,
|
||||
Hard,
|
||||
Inter,
|
||||
Wet,
|
||||
Undefined
|
||||
}
|
||||
public Type Coumpound;
|
||||
public int NumberOfLaps;
|
||||
public Tyre(Type type, int laps)
|
||||
{
|
||||
Coumpound = type;
|
||||
NumberOfLaps = laps;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverDrsWindow.cs
|
||||
/// Brief : Window containing DRS related method and infos
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Tesseract;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal class DriverDrsWindow:Window
|
||||
{
|
||||
private static int EmptyDrsGreenValue = -1;
|
||||
private static Random rnd = new Random();
|
||||
public DriverDrsWindow(Bitmap image, Rectangle bounds,bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "DRS";
|
||||
}
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
bool result = false;
|
||||
int greenValue = GetGreenPixels();
|
||||
if (EmptyDrsGreenValue == -1)
|
||||
EmptyDrsGreenValue = greenValue;
|
||||
|
||||
if (greenValue > EmptyDrsGreenValue + EmptyDrsGreenValue / 100 * 30)
|
||||
result = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
private unsafe int GetGreenPixels()
|
||||
{
|
||||
int tot = 0;
|
||||
|
||||
Bitmap bmp = WindowImage;
|
||||
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
||||
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
for (int y = 0; y < bmp.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < bmp.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
byte blue = pixel[0];
|
||||
byte green = pixel[1];
|
||||
byte red = pixel[2];
|
||||
|
||||
if (green > blue * 1.5 && green > red * 1.5)
|
||||
{
|
||||
tot++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bmp.UnlockBits(bmpData);
|
||||
|
||||
return tot;
|
||||
}
|
||||
public Rectangle GetBox()
|
||||
{
|
||||
var tessImage = Pix.LoadFromMemory(ImageToByte(WindowImage));
|
||||
Engine.SetVariable("tessedit_char_whitelist", "");
|
||||
Page page = Engine.Process(tessImage);
|
||||
|
||||
using (var iter = page.GetIterator())
|
||||
{
|
||||
iter.Begin();
|
||||
do
|
||||
{
|
||||
Rect boundingBox;
|
||||
|
||||
// Get the bounding box for the current element
|
||||
if (iter.TryGetBoundingBox(PageIteratorLevel.Word, out boundingBox))
|
||||
{
|
||||
page.Dispose();
|
||||
return new Rectangle(boundingBox.X1, boundingBox.X2, boundingBox.Width, boundingBox.Height);
|
||||
}
|
||||
} while (iter.Next(PageIteratorLevel.Word));
|
||||
|
||||
page.Dispose();
|
||||
return new Rectangle(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverGapToLeaderWindow.cs
|
||||
/// Brief : Window containing infos about the gap to the leader of a driver
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal class DriverGapToLeaderWindow:Window
|
||||
{
|
||||
public DriverGapToLeaderWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "GapToLeader";
|
||||
}
|
||||
/// <summary>
|
||||
/// Decodes the gap to leader using Tesseract OCR
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
int result = await GetTimeFromPng(WindowImage, OcrImage.WindowType.Gap, Engine);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverLapTimeWindow
|
||||
/// Brief : Window containing infos about the lap time of a driver
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal class DriverLapTimeWindow:Window
|
||||
{
|
||||
public DriverLapTimeWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "LapTime";
|
||||
}
|
||||
/// <summary>
|
||||
/// Decodes the lap time contained in the image using OCR Tesseract
|
||||
/// </summary>
|
||||
/// <returns>The laptime in int (ms)</returns>
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
int result = await GetTimeFromPng(WindowImage, OcrImage.WindowType.LapTime, Engine);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverNameWindow
|
||||
/// Brief : Window containing infos about the name of the driver
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class DriverNameWindow : Window
|
||||
{
|
||||
public static Random rnd = new Random();
|
||||
public DriverNameWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "Name";
|
||||
}
|
||||
/// <summary>
|
||||
/// Decodes using OCR wich driver name is in the image
|
||||
/// </summary>
|
||||
/// <param name="DriverList"></param>
|
||||
/// <returns>The driver name in string</returns>
|
||||
public override async Task<object> DecodePng(List<string> DriverList)
|
||||
{
|
||||
string result = "";
|
||||
result = await GetStringFromPng(WindowImage, Engine);
|
||||
|
||||
if (!IsADriver(DriverList, result))
|
||||
{
|
||||
//I put everything in uppercase to try to lower the chances of bad answers
|
||||
result = FindClosestMatch(DriverList.ConvertAll(d => d.ToUpper()), result.ToUpper());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that the name found in the OCR is a valid name
|
||||
/// </summary>
|
||||
/// <param name="driverList"></param>
|
||||
/// <param name="potentialDriver"></param>
|
||||
/// <returns>If ye or no the driver exists</returns>
|
||||
private static bool IsADriver(List<string> driverList, string potentialDriver)
|
||||
{
|
||||
bool result = false;
|
||||
//I cant use drivers.Contains because it has missmatched cases and all
|
||||
foreach (string name in driverList)
|
||||
{
|
||||
if (name.ToUpper() == potentialDriver.ToUpper())
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverPosition.cs
|
||||
/// Brief : Window containing infos about the position of a driver.
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class DriverPositionWindow:Window
|
||||
{
|
||||
public DriverPositionWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "Position";
|
||||
}
|
||||
/// <summary>
|
||||
/// Decodes the position number using Tesseract OCR
|
||||
/// </summary>
|
||||
/// <returns>The position of the pilot in int</returns>
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
string ocrResult = await GetStringFromPng(WindowImage, Engine, "0123456789");
|
||||
|
||||
int position;
|
||||
try
|
||||
{
|
||||
position = Convert.ToInt32(ocrResult);
|
||||
}
|
||||
catch
|
||||
{
|
||||
position = -1;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverSectorWindow.cs
|
||||
/// Brief : Window containing infos about a driver sector time. Can be the first second or third, does not matter.
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal class DriverSectorWindow:Window
|
||||
{
|
||||
public DriverSectorWindow(Bitmap image, Rectangle bounds, int sectorId, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "Sector"+sectorId;
|
||||
}
|
||||
/// <summary>
|
||||
/// Decodes the sector
|
||||
/// </summary>
|
||||
/// <returns>the sector time in int (ms)</returns>
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
int ocrResult = await GetTimeFromPng(WindowImage, OcrImage.WindowType.Sector, Engine);
|
||||
return ocrResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverTyresWindow.cs
|
||||
/// Brief : Window containing infos about a driver's tyre
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class DriverTyresWindow:Window
|
||||
{
|
||||
private static Random rnd = new Random();
|
||||
int seed = rnd.Next(0, 10000);
|
||||
|
||||
//Those are the colors I found but you can change them if they change in the future like in 2019
|
||||
public static Color SOFT_TYRE_COLOR = Color.FromArgb(0xff, 0x00, 0x00);
|
||||
public static Color MEDIUM_TYRE_COLOR = Color.FromArgb(0xf5, 0xbf, 0x00);
|
||||
public static Color HARD_TYRE_COLOR = Color.FromArgb(0xa4, 0xa5, 0xa8);
|
||||
public static Color INTER_TYRE_COLOR = Color.FromArgb(0x00, 0xa4, 0x2e);
|
||||
public static Color WET_TYRE_COLOR = Color.FromArgb(0x27, 0x60, 0xa6);
|
||||
public static Color EMPTY_COLOR = Color.FromArgb(0x20, 0x20, 0x20);
|
||||
|
||||
public DriverTyresWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "Tyres";
|
||||
}
|
||||
/// <summary>
|
||||
/// This will decode the content of the image
|
||||
/// </summary>
|
||||
/// <returns>And object containing what was on the image</returns>
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
return await GetTyreInfos();
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that will decode whats on the image and return the tyre infos it could manage to recover
|
||||
/// </summary>
|
||||
/// <returns>A tyre object containing tyre infos</returns>
|
||||
private async Task<Tyre> GetTyreInfos()
|
||||
{
|
||||
Bitmap tyreZone = GetSmallBitmapFromBigOne(WindowImage, FindTyreZone());
|
||||
Tyre.Type type = Tyre.Type.Undefined;
|
||||
type = GetTyreTypeFromColor(OcrImage.GetAvgColorFromBitmap(tyreZone));
|
||||
int laps = -1;
|
||||
|
||||
string number = await GetStringFromPng(tyreZone, Engine, "0123456789", OcrImage.WindowType.Tyre);
|
||||
try
|
||||
{
|
||||
laps = Convert.ToInt32(number);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//We could not convert the number so its a letter so its 0 laps old
|
||||
laps = 0;
|
||||
}
|
||||
//tyreZone.Save(Reader.DEBUG_DUMP_FOLDER + "Tyre" + type + "Laps" + laps + '#' + rnd.Next(0, 1000) + ".png");
|
||||
return new Tyre(type, laps);
|
||||
}
|
||||
/// <summary>
|
||||
/// Finds where the important part of the image is
|
||||
/// </summary>
|
||||
/// <returns>A rectangle containing position and dimensions of the important part of the image</returns>
|
||||
private Rectangle FindTyreZone()
|
||||
{
|
||||
Bitmap bmp = WindowImage;
|
||||
int currentPosition = bmp.Width;
|
||||
int height = bmp.Height / 2;
|
||||
Color limitColor = Color.FromArgb(0x50, 0x50, 0x50);
|
||||
Color currentColor = Color.FromArgb(0, 0, 0);
|
||||
|
||||
Size newWindowSize = new Size(bmp.Height - Convert.ToInt32((float)bmp.Height / 100f * 25f), bmp.Height - Convert.ToInt32((float)bmp.Height / 100f * 35f));
|
||||
|
||||
while (currentColor.R <= limitColor.R && currentColor.G <= limitColor.G && currentColor.B <= limitColor.B && currentPosition > 0)
|
||||
{
|
||||
currentPosition--;
|
||||
currentColor = bmp.GetPixel(currentPosition, height);
|
||||
}
|
||||
|
||||
//Its here to let the new window include a little bit of the right
|
||||
int CorrectedX = currentPosition - (newWindowSize.Width) + Convert.ToInt32((float)newWindowSize.Width / 100f * 10f);
|
||||
int CorrectedY = Convert.ToInt32((float)newWindowSize.Height / 100f * 35f);
|
||||
if (CorrectedX <= 0)
|
||||
return new Rectangle(0, 0, newWindowSize.Width, newWindowSize.Height);
|
||||
|
||||
return new Rectangle(CorrectedX, CorrectedY, newWindowSize.Width, newWindowSize.Height);
|
||||
}
|
||||
//This method has been created with the help of chatGPT
|
||||
/// <summary>
|
||||
/// Methods that compares a list of colors to see wich is the closest from the input color and decide wich tyre type it is
|
||||
/// </summary>
|
||||
/// <param name="inputColor">The color that you found</param>
|
||||
/// <returns>The tyre type</returns>
|
||||
public Tyre.Type GetTyreTypeFromColor(Color inputColor)
|
||||
{
|
||||
Tyre.Type type = Tyre.Type.Undefined;
|
||||
List<Color> colors = new List<Color>();
|
||||
//dont forget that if for some reason someday F1 adds a new Tyre type you will need to add it in the constants but also here in the list
|
||||
//You will also need to add it below in the Tyre object's enum and add an if in the end of this method
|
||||
colors.Add(SOFT_TYRE_COLOR);
|
||||
colors.Add(MEDIUM_TYRE_COLOR);
|
||||
colors.Add(HARD_TYRE_COLOR);
|
||||
colors.Add(INTER_TYRE_COLOR);
|
||||
colors.Add(WET_TYRE_COLOR);
|
||||
colors.Add(EMPTY_COLOR);
|
||||
|
||||
Color closestColor = colors[0];
|
||||
int closestDistance = int.MaxValue;
|
||||
foreach (Color color in colors)
|
||||
{
|
||||
int distance = Math.Abs(color.R - inputColor.R) + Math.Abs(color.G - inputColor.G) + Math.Abs(color.B - inputColor.B);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestColor = color;
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
//We cant use a switch as the colors cant be constants ...
|
||||
if (closestColor == SOFT_TYRE_COLOR)
|
||||
type = Tyre.Type.Soft;
|
||||
if (closestColor == MEDIUM_TYRE_COLOR)
|
||||
type = Tyre.Type.Medium;
|
||||
if (closestColor == HARD_TYRE_COLOR)
|
||||
type = Tyre.Type.Hard;
|
||||
if (closestColor == INTER_TYRE_COLOR)
|
||||
type = Tyre.Type.Inter;
|
||||
if (closestColor == WET_TYRE_COLOR)
|
||||
type = Tyre.Type.Wet;
|
||||
if (closestColor == EMPTY_COLOR)
|
||||
return Tyre.Type.Undefined;
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : F1TVEmulator.cs
|
||||
/// Brief : Class that contains methods to emulate a browser and navigate the F1TV website
|
||||
/// Version : 0.1
|
||||
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Firefox;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
using OpenQA.Selenium.Support.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal class F1TVEmulator
|
||||
{
|
||||
public const string COOKIE_HOST = ".formula1.com";
|
||||
public const string PYTHON_COOKIE_RETRIEVAL_FILENAME = "recoverCookiesCSV.py";
|
||||
public const string GECKODRIVER_FILENAME = @"geckodriver-v0.27.0-win64\geckodriver.exe";
|
||||
//BE CAREFULL IF YOU CHANGE IT HERE YOU NEED TO CHANGE IT IN THE PYTHON SCRIPT TOO
|
||||
public const string COOKIES_CSV_FILENAME = "cookies.csv";
|
||||
|
||||
private FirefoxDriver Driver;
|
||||
|
||||
private bool _ready;
|
||||
private string _grandPrixUrl;
|
||||
public string GrandPrixUrl { get => _grandPrixUrl; private set => _grandPrixUrl = value; }
|
||||
public bool Ready { get => _ready; set => _ready = value; }
|
||||
public F1TVEmulator(string grandPrixUrl)
|
||||
{
|
||||
GrandPrixUrl = grandPrixUrl;
|
||||
Ready = false;
|
||||
}
|
||||
private void StartCookieRecovering()
|
||||
{
|
||||
string scriptPath = PYTHON_COOKIE_RETRIEVAL_FILENAME;
|
||||
Process process = new Process();
|
||||
process.StartInfo.FileName = "python.exe";
|
||||
process.StartInfo.Arguments = scriptPath;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.Start();
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
}
|
||||
public string GetCookie(string host, string name)
|
||||
{
|
||||
StartCookieRecovering();
|
||||
string value = "";
|
||||
List<Cookie> cookies = new List<Cookie>();
|
||||
using (var reader = new StreamReader(COOKIES_CSV_FILENAME))
|
||||
{
|
||||
// Read the header row and validate column order
|
||||
string header = reader.ReadLine();
|
||||
string[] expectedColumns = { "host_key", "name", "value", "path", "expires_utc", "is_secure", "is_httponly" };
|
||||
string[] actualColumns = header.Split(',');
|
||||
for (int i = 0; i < expectedColumns.Length; i++)
|
||||
{
|
||||
if (expectedColumns[i] != actualColumns[i])
|
||||
{
|
||||
throw new InvalidOperationException($"Expected column '{expectedColumns[i]}' at index {i} but found '{actualColumns[i]}'");
|
||||
}
|
||||
}
|
||||
|
||||
// Read each data row and parse values into a Cookie object
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
string line = reader.ReadLine();
|
||||
string[] fields = line.Split(',');
|
||||
|
||||
string hostname = fields[0];
|
||||
string cookieName = fields[1];
|
||||
|
||||
if (hostname == host && cookieName == name)
|
||||
{
|
||||
value = fields[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
public async Task<int> Start()
|
||||
{
|
||||
Ready = false;
|
||||
|
||||
string loginCookieName = "login";
|
||||
string loginSessionCookieName = "login-session";
|
||||
string loginCookieValue = GetCookie(COOKIE_HOST, loginCookieName);
|
||||
string loginSessionValue = GetCookie(COOKIE_HOST, loginSessionCookieName);
|
||||
|
||||
int windowWidth = 1920;
|
||||
int windowHeight = 768;
|
||||
|
||||
var service = FirefoxDriverService.CreateDefaultService(GECKODRIVER_FILENAME);
|
||||
service.Host = "127.0.0.1";
|
||||
service.Port = 5555;
|
||||
|
||||
FirefoxProfile profile = new FirefoxProfile();
|
||||
FirefoxOptions options = new FirefoxOptions();
|
||||
//profile.SetPreference("full-screen-api.ignore-widgets", true);
|
||||
//profile.SetPreference("media.hardware-video-decoding.enabled", true);
|
||||
//profile.SetPreference("full-screen-api.enabled", true);
|
||||
options.Profile = profile;
|
||||
profile.SetPreference("layout.css.devPixelsPerPx", "1.0");
|
||||
|
||||
options.AcceptInsecureCertificates = true;
|
||||
options.AddArgument("--headless");
|
||||
//options.AddArgument("--start-maximized");
|
||||
//options.AddArgument("--window-size=1920x1080");
|
||||
//options.AddArgument("--width=" + windowWidth);
|
||||
//options.AddArgument("--height=" + windowHeight);
|
||||
//options.AddArgument("-window-size=1920x1080");
|
||||
//options.AddArgument("--width=1920");
|
||||
//options.AddArgument("--height=1080");
|
||||
//profile
|
||||
|
||||
try
|
||||
{
|
||||
Driver = new FirefoxDriver(service, options);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Ready = false;
|
||||
return 101;
|
||||
}
|
||||
|
||||
Actions actions = new Actions(Driver);
|
||||
var loginCookie = new Cookie(loginCookieName, loginCookieValue, COOKIE_HOST, "/", DateTime.Now.AddDays(5));
|
||||
var loginSessionCookie = new Cookie(loginSessionCookieName, loginSessionValue, COOKIE_HOST, "/", DateTime.Now.AddDays(5));
|
||||
|
||||
Driver.Navigate().GoToUrl("https://f1tv.formula1.com/");
|
||||
|
||||
Driver.Manage().Cookies.AddCookie(loginCookie);
|
||||
Driver.Manage().Cookies.AddCookie(loginSessionCookie);
|
||||
|
||||
try
|
||||
{
|
||||
Driver.Navigate().GoToUrl(GrandPrixUrl);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//The url is not a valid url
|
||||
Driver.Dispose();
|
||||
return 103;
|
||||
}
|
||||
|
||||
//Waits for the page to fully load
|
||||
Driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(30);
|
||||
|
||||
//Removes the cookie prompt
|
||||
try
|
||||
{
|
||||
IWebElement conscentButton = Driver.FindElement(By.Id("truste-consent-button"));
|
||||
conscentButton.Click();
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Could not locate the cookie button
|
||||
Screenshot("ERROR104");
|
||||
Driver.Dispose();
|
||||
return 104;
|
||||
}
|
||||
|
||||
//Again waits for the page to fully load (when you accept cookies it takes a little time for the page to load)
|
||||
//Cannot use The timeout because the feed loading is not really loading so there is not event or anything
|
||||
Thread.Sleep(5000);
|
||||
|
||||
//Switches to the Data channel
|
||||
try
|
||||
{
|
||||
IWebElement dataChannelButton = Driver.FindElement(By.ClassName("data-button"));
|
||||
dataChannelButton.Click();
|
||||
}
|
||||
catch
|
||||
{
|
||||
//If the data button does not exists its because the user is not connected
|
||||
Screenshot("ERROR102");
|
||||
Driver.Dispose();
|
||||
return 102;
|
||||
}
|
||||
|
||||
//Open settings
|
||||
// Press the space key, this should make the setting button visible
|
||||
// It does not matter if the feed is paused because when changing channel it autoplays
|
||||
actions.SendKeys(OpenQA.Selenium.Keys.Space).Perform();
|
||||
//Clicks on the settings Icon
|
||||
|
||||
int tries = 0;
|
||||
bool success = false;
|
||||
while (tries < 100 && !success)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
try
|
||||
{
|
||||
IWebElement settingsButton = Driver.FindElement(By.ClassName("bmpui-ui-settingstogglebutton"));
|
||||
settingsButton.Click();
|
||||
IWebElement selectElement = Driver.FindElement(By.ClassName("bmpui-ui-videoqualityselectbox"));
|
||||
SelectElement select = new SelectElement(selectElement);
|
||||
IWebElement selectOption = selectElement.FindElement(By.CssSelector("option[value^='1080_']"));
|
||||
selectOption.Click();
|
||||
success = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Sometimes it can crash because it could not get the options to show up in time. When it happens just retry
|
||||
success = false;
|
||||
tries++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Screenshot("ERROR105");
|
||||
Driver.Dispose();
|
||||
return 105;
|
||||
}
|
||||
|
||||
Screenshot("BEFOREFULLSCREEN");
|
||||
|
||||
//Makes the feed fullscreen
|
||||
//Driver.Manage().Window.Size = new System.Drawing.Size(windowWidth, windowHeight);
|
||||
Driver.Manage().Window.Maximize();
|
||||
WebDriverWait wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(10));
|
||||
try
|
||||
{
|
||||
IWebElement fullScreenButton = Driver.FindElement(By.ClassName("bmpui-ui-fullscreentogglebutton"));
|
||||
fullScreenButton.Click();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Screenshot("ERROR106");
|
||||
Driver.Dispose();
|
||||
return 106;
|
||||
}
|
||||
|
||||
Screenshot("AFTERFULLSCREEN");
|
||||
|
||||
//STARTUP FINISHED READY TO SCREENSHOT
|
||||
Ready = true;
|
||||
return 0;
|
||||
}
|
||||
public Bitmap Screenshot(string name = "TEST")
|
||||
{
|
||||
Bitmap result = new Bitmap(4242, 6969);
|
||||
try
|
||||
{
|
||||
//Screenshot scrsht = ((ITakesScreenshot)Driver).GetScreenshot();
|
||||
//profileriver.SetPreference("layout.css.devPixelsPerPx", "1.0");
|
||||
|
||||
//Screenshot scrsht = Driver.GetFullPageScreenshot();
|
||||
Screenshot scrsht = Driver.GetScreenshot();
|
||||
|
||||
|
||||
byte[] screenshotBytes = Convert.FromBase64String(scrsht.AsBase64EncodedString);
|
||||
MemoryStream stream = new MemoryStream(screenshotBytes);
|
||||
|
||||
result = new Bitmap(stream);
|
||||
//result.Save(name + ".png");
|
||||
scrsht.SaveAsFile(name + ".png");
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Nothing for now
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public void Stop()
|
||||
{
|
||||
Ready = false;
|
||||
Driver.Dispose();
|
||||
}
|
||||
public void ResetDriver()
|
||||
{
|
||||
Ready = false;
|
||||
Driver.Dispose();
|
||||
Driver = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public partial class Form1 : Form
|
||||
{
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void btnSettings_Click(object sender, EventArgs e)
|
||||
{
|
||||
Settings settingsForm = new Settings();
|
||||
settingsForm.ShowDialog();
|
||||
MessageBox.Show(settingsForm.GrandPrixUrl + Environment.NewLine + settingsForm.GrandPrixName + Environment.NewLine + settingsForm.GrandPrixYear);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,539 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : OcrImage.cs
|
||||
/// Brief : Class containing all the methods used to enhance images for OCR
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class OcrImage
|
||||
{
|
||||
//this is a hardcoded value based on the colors of the F1TV data channel background you can change it if sometime in the future the color changes
|
||||
//Any color that has any of its R,G or B channel higher than the treshold will be considered as being usefull information
|
||||
public static Color F1TV_BACKGROUND_TRESHOLD = Color.FromArgb(0x50, 0x50, 0x50);
|
||||
Bitmap InputBitmap;
|
||||
public enum WindowType
|
||||
{
|
||||
LapTime,
|
||||
Text,
|
||||
Sector,
|
||||
Gap,
|
||||
Tyre,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new Ocr image to help enhance the given bitmap for OCR
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The image you want to enhance</param>
|
||||
public OcrImage(Bitmap inputBitmap)
|
||||
{
|
||||
InputBitmap = inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Enhances the image depending on wich type of window the image comes from
|
||||
/// </summary>
|
||||
/// <param name="type">The type of the window. Depending on it different enhancing features will be applied</param>
|
||||
/// <returns>The enhanced Bitmap</returns>
|
||||
public Bitmap Enhance(WindowType type = WindowType.Text)
|
||||
{
|
||||
Bitmap outputBitmap = (Bitmap)InputBitmap.Clone();
|
||||
switch (type)
|
||||
{
|
||||
case WindowType.LapTime:
|
||||
outputBitmap = Tresholding(outputBitmap, 185);
|
||||
outputBitmap = Resize(outputBitmap, 2);
|
||||
outputBitmap = Dilatation(outputBitmap, 1);
|
||||
outputBitmap = Erode(outputBitmap, 1);
|
||||
break;
|
||||
case WindowType.Text:
|
||||
outputBitmap = InvertColors(outputBitmap);
|
||||
outputBitmap = Tresholding(outputBitmap, 165);
|
||||
outputBitmap = Resize(outputBitmap, 2);
|
||||
outputBitmap = Dilatation(outputBitmap, 1);
|
||||
break;
|
||||
case WindowType.Tyre:
|
||||
outputBitmap = RemoveUseless(outputBitmap);
|
||||
outputBitmap = Resize(outputBitmap, 4);
|
||||
outputBitmap = Dilatation(outputBitmap, 1);
|
||||
break;
|
||||
default:
|
||||
outputBitmap = Tresholding(outputBitmap, 165);
|
||||
outputBitmap = Resize(outputBitmap, 4);
|
||||
outputBitmap = Erode(outputBitmap, 1);
|
||||
break;
|
||||
}
|
||||
return outputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that convert a colored RGB bitmap into a GrayScale image
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The Bitmap you want to convert</param>
|
||||
/// <returns>The bitmap in grayscale</returns>
|
||||
public static Bitmap Grayscale(Bitmap inputBitmap)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
byte blue = pixel[0];
|
||||
byte green = pixel[1];
|
||||
byte red = pixel[2];
|
||||
|
||||
//Those a specific values to correct the weights so its more pleasing to the human eye
|
||||
int gray = (int)(red * 0.3 + green * 0.59 + blue * 0.11);
|
||||
|
||||
pixel[0] = pixel[1] = pixel[2] = (byte)gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
|
||||
return inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that binaries the input image up to a certain treshold given
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">the bitmap you want to convert to binary colors</param>
|
||||
/// <param name="threshold">The floor at wich the color is considered as white or black</param>
|
||||
/// <returns>The binarised bitmap</returns>
|
||||
public static Bitmap Tresholding(Bitmap inputBitmap, int threshold)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
int bmpHeight = inputBitmap.Height;
|
||||
int bmpWidth = inputBitmap.Width;
|
||||
Parallel.For(0, bmpHeight, y =>
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < bmpWidth; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
byte blue = pixel[0];
|
||||
byte green = pixel[1];
|
||||
byte red = pixel[2];
|
||||
//Those a specific values to correct the weights so its more pleasing to the human eye
|
||||
int gray = (int)(red * 0.3 + green * 0.59 + blue * 0.11);
|
||||
int value = gray < threshold ? 0 : 255;
|
||||
|
||||
pixel[0] = pixel[1] = pixel[2] = (byte)value;
|
||||
}
|
||||
});
|
||||
}
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
|
||||
return inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that removes the pixels that are flagged as background
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to remove the background from</param>
|
||||
/// <returns>The Bitmap without the background</returns>
|
||||
public static Bitmap RemoveBG(Bitmap inputBitmap)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
int B = pixel[0];
|
||||
int G = pixel[1];
|
||||
int R = pixel[2];
|
||||
|
||||
if (R <= F1TV_BACKGROUND_TRESHOLD.R && G <= F1TV_BACKGROUND_TRESHOLD.G && B <= F1TV_BACKGROUND_TRESHOLD.B)
|
||||
pixel[0] = pixel[1] = pixel[2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
|
||||
return inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that removes all the useless things from the image and returns hopefully only the numbers
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to remove useless things from (Expects a cropped part of the TyreWindow)</param>
|
||||
/// <returns>The bitmap with (hopefully) only the digits</returns>
|
||||
public unsafe static Bitmap RemoveUseless(Bitmap inputBitmap)
|
||||
{
|
||||
//Note you can use something else than a cropped tyre window but I would recommend checking the code first to see if it fits your intended use
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
|
||||
List<int> pixelsToRemove = new List<int>();
|
||||
|
||||
bool fromBorder = true;
|
||||
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
int B = pixel[0];
|
||||
int G = pixel[1];
|
||||
int R = pixel[2];
|
||||
|
||||
if (fromBorder && B < F1TV_BACKGROUND_TRESHOLD.B && G < F1TV_BACKGROUND_TRESHOLD.G && R < F1TV_BACKGROUND_TRESHOLD.R)
|
||||
{
|
||||
pixelsToRemove.Add(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fromBorder)
|
||||
{
|
||||
fromBorder = false;
|
||||
pixelsToRemove.Add(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
fromBorder = true;
|
||||
for (int x = inputBitmap.Width - 1; x > 0; x--)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
int B = pixel[0];
|
||||
int G = pixel[1];
|
||||
int R = pixel[2];
|
||||
|
||||
if (fromBorder && B < F1TV_BACKGROUND_TRESHOLD.B && G < F1TV_BACKGROUND_TRESHOLD.G && R < F1TV_BACKGROUND_TRESHOLD.R)
|
||||
{
|
||||
pixelsToRemove.Add(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fromBorder)
|
||||
{
|
||||
fromBorder = false;
|
||||
pixelsToRemove.Add(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (int pxPos in pixelsToRemove)
|
||||
{
|
||||
byte* pixel = currentLine + (pxPos * bytesPerPixel);
|
||||
|
||||
pixel[0] = 0xFF;
|
||||
pixel[1] = 0xFF;
|
||||
pixel[2] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
//Removing the color parts
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
int B = pixel[0];
|
||||
int G = pixel[1];
|
||||
int R = pixel[2];
|
||||
|
||||
if (R >= F1TV_BACKGROUND_TRESHOLD.R + 15 || G >= F1TV_BACKGROUND_TRESHOLD.G + 15 || B >= F1TV_BACKGROUND_TRESHOLD.B + 15)
|
||||
{
|
||||
pixel[0] = 0xFF;
|
||||
pixel[1] = 0xFF;
|
||||
pixel[2] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
return inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Recovers the average colors from the Image. NOTE : It wont take in account colors that are lower than the background
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to get the average color from</param>
|
||||
/// <returns>The average color of the bitmap</returns>
|
||||
public static Color GetAvgColorFromBitmap(Bitmap inputBitmap)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
int totR = 0;
|
||||
int totG = 0;
|
||||
int totB = 0;
|
||||
|
||||
int totPixels = 1;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
int bmpHeight = inputBitmap.Height;
|
||||
int bmpWidth = inputBitmap.Width;
|
||||
Parallel.For(0, bmpHeight, y =>
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < bmpWidth; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
int B = pixel[0];
|
||||
int G = pixel[1];
|
||||
int R = pixel[2];
|
||||
|
||||
if (R >= F1TV_BACKGROUND_TRESHOLD.R || G >= F1TV_BACKGROUND_TRESHOLD.G || B >= F1TV_BACKGROUND_TRESHOLD.B)
|
||||
{
|
||||
totPixels++;
|
||||
totB += pixel[0];
|
||||
totG += pixel[1];
|
||||
totR += pixel[2];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
|
||||
return Color.FromArgb(255, Convert.ToInt32((float)totR / (float)totPixels), Convert.ToInt32((float)totG / (float)totPixels), Convert.ToInt32((float)totB / (float)totPixels));
|
||||
}
|
||||
/// <summary>
|
||||
/// This method simply inverts all the colors in a Bitmap
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">the bitmap you want to invert the colors from</param>
|
||||
/// <returns>The bitmap with inverted colors</returns>
|
||||
public static Bitmap InvertColors(Bitmap inputBitmap)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
pixel[0] = (byte)(255 - pixel[0]);
|
||||
pixel[1] = (byte)(255 - pixel[1]);
|
||||
pixel[2] = (byte)(255 - pixel[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
|
||||
return inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Methods that applies Bicubic interpolation to increase the size and resolution of an image
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to resize</param>
|
||||
/// <param name="resizeFactor">The factor of resizing you want to use. I recommend using even numbers</param>
|
||||
/// <returns>The bitmap witht the new size</returns>
|
||||
public static Bitmap Resize(Bitmap inputBitmap, int resizeFactor)
|
||||
{
|
||||
var resultBitmap = new Bitmap(inputBitmap.Width * resizeFactor, inputBitmap.Height * resizeFactor);
|
||||
|
||||
using (var graphics = Graphics.FromImage(resultBitmap))
|
||||
{
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.DrawImage(inputBitmap, new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height));
|
||||
}
|
||||
|
||||
return resultBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// method that Highlights the countours of a Bitmap
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to highlight the countours of</param>
|
||||
/// <returns>The bitmap with countours highlighted</returns>
|
||||
public static Bitmap HighlightContours(Bitmap inputBitmap)
|
||||
{
|
||||
Bitmap outputBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height);
|
||||
|
||||
Bitmap grayscale = Grayscale(inputBitmap);
|
||||
Bitmap thresholded = Tresholding(grayscale, 128);
|
||||
Bitmap dilated = Dilatation(thresholded, 3);
|
||||
Bitmap eroded = Erode(dilated, 3);
|
||||
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
Color pixel = inputBitmap.GetPixel(x, y);
|
||||
Color dilatedPixel = dilated.GetPixel(x, y);
|
||||
Color erodedPixel = eroded.GetPixel(x, y);
|
||||
|
||||
int gray = (int)(pixel.R * 0.3 + pixel.G * 0.59 + pixel.B * 0.11);
|
||||
int threshold = dilatedPixel.R;
|
||||
|
||||
if (gray > threshold)
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(255, 255, 255));
|
||||
}
|
||||
else if (gray <= threshold && erodedPixel.R == 0)
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(255, 0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that that erodes the morphology of a bitmap
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to erode</param>
|
||||
/// <param name="kernelSize">The amount of Erosion you want (be carefull its expensive on ressources)</param>
|
||||
/// <returns>The Bitmap with the eroded contents</returns>
|
||||
public static Bitmap Erode(Bitmap inputBitmap, int kernelSize)
|
||||
{
|
||||
Bitmap outputBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height);
|
||||
|
||||
int[,] kernel = new int[kernelSize, kernelSize];
|
||||
|
||||
for (int i = 0; i < kernelSize; i++)
|
||||
{
|
||||
for (int j = 0; j < kernelSize; j++)
|
||||
{
|
||||
kernel[i, j] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = kernelSize / 2; y < inputBitmap.Height - kernelSize / 2; y++)
|
||||
{
|
||||
for (int x = kernelSize / 2; x < inputBitmap.Width - kernelSize / 2; x++)
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
for (int i = -kernelSize / 2; i <= kernelSize / 2; i++)
|
||||
{
|
||||
for (int j = -kernelSize / 2; j <= kernelSize / 2; j++)
|
||||
{
|
||||
Color pixel = inputBitmap.GetPixel(x + i, y + j);
|
||||
int gray = (int)(pixel.R * 0.3 + pixel.G * 0.59 + pixel.B * 0.11);
|
||||
|
||||
if (gray >= 128 && kernel[i + kernelSize / 2, j + kernelSize / 2] == 1)
|
||||
{
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that that use dilatation of the morphology of a bitmap
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to use dilatation on</param>
|
||||
/// <param name="kernelSize">The amount of dilatation you want (be carefull its expensive on ressources)</param>
|
||||
/// <returns>The Bitmap after Dilatation</returns>
|
||||
public static Bitmap Dilatation(Bitmap inputBitmap, int kernelSize)
|
||||
{
|
||||
Bitmap outputBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height);
|
||||
|
||||
int[,] kernel = new int[kernelSize, kernelSize];
|
||||
|
||||
for (int i = 0; i < kernelSize; i++)
|
||||
{
|
||||
for (int j = 0; j < kernelSize; j++)
|
||||
{
|
||||
kernel[i, j] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = kernelSize / 2; y < inputBitmap.Height - kernelSize / 2; y++)
|
||||
{
|
||||
for (int x = kernelSize / 2; x < inputBitmap.Width - kernelSize / 2; x++)
|
||||
{
|
||||
bool flag = false;
|
||||
|
||||
for (int i = -kernelSize / 2; i <= kernelSize / 2; i++)
|
||||
{
|
||||
for (int j = -kernelSize / 2; j <= kernelSize / 2; j++)
|
||||
{
|
||||
Color pixel = inputBitmap.GetPixel(x + i, y + j);
|
||||
int gray = (int)(pixel.R * 0.3 + pixel.G * 0.59 + pixel.B * 0.11);
|
||||
|
||||
if (gray < 128 && kernel[i + kernelSize / 2, j + kernelSize / 2] == 1)
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(255, 255, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputBitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : Reader.cs
|
||||
/// Brief : Class used to Read the config file for the OCR
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class Reader
|
||||
{
|
||||
const int NUMBER_OF_DRIVERS = 20;
|
||||
public List<string> Drivers;
|
||||
public List<Zone> MainZones;
|
||||
|
||||
public Reader(string configFile, Bitmap image,bool loadOCR = true)
|
||||
{
|
||||
MainZones = Load(image,configFile,ref Drivers,loadOCR);
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that reads the JSON config file and create all the Zones and Windows
|
||||
/// </summary>
|
||||
/// <param name="imageNumber">The image #id on wich you want to create the zones on</param>
|
||||
public static List<Zone> Load(Bitmap image,string configFilePath,ref List<string> driverListToFill,bool LoadOCR)
|
||||
{
|
||||
List<Zone> mainZones = new List<Zone>();
|
||||
Bitmap fullImage = image;
|
||||
List<string> drivers;
|
||||
Zone mainZone;
|
||||
|
||||
try
|
||||
{
|
||||
using (var streamReader = new StreamReader(configFilePath))
|
||||
{
|
||||
var jsonText = streamReader.ReadToEnd();
|
||||
var jsonDocument = JsonDocument.Parse(jsonText);
|
||||
|
||||
var driversNames = jsonDocument.RootElement.GetProperty("Drivers");
|
||||
driverListToFill = new List<string>();
|
||||
|
||||
foreach (var nameElement in driversNames.EnumerateArray())
|
||||
{
|
||||
driverListToFill.Add(nameElement.GetString());
|
||||
}
|
||||
|
||||
var mainProperty = jsonDocument.RootElement.GetProperty("Main");
|
||||
Point MainPosition = new Point(mainProperty.GetProperty("x").GetInt32(), mainProperty.GetProperty("y").GetInt32());
|
||||
Size MainSize = new Size(mainProperty.GetProperty("width").GetInt32(), mainProperty.GetProperty("height").GetInt32());
|
||||
Rectangle MainRectangle = new Rectangle(MainPosition, MainSize);
|
||||
mainZone = new Zone(image, MainRectangle,"Main");
|
||||
|
||||
var zones = mainProperty.GetProperty("Zones");
|
||||
var driverZone = zones[0].GetProperty("DriverZone");
|
||||
|
||||
Point FirstZonePosition = new Point(driverZone.GetProperty("x").GetInt32(), driverZone.GetProperty("y").GetInt32());
|
||||
Size FirstZoneSize = new Size(driverZone.GetProperty("width").GetInt32(), driverZone.GetProperty("height").GetInt32());
|
||||
|
||||
var windows = driverZone.GetProperty("Windows");
|
||||
|
||||
var driverPosition = windows[0].GetProperty("Position");
|
||||
Size driverPositionArea = new Size(driverPosition.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverPositionPosition = new Point(driverPosition.GetProperty("x").GetInt32(), driverPosition.GetProperty("y").GetInt32());
|
||||
|
||||
var driverGapToLeader = windows[0].GetProperty("GapToLeader");
|
||||
Size driverGapToLeaderArea = new Size(driverGapToLeader.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverGapToLeaderPosition = new Point(driverGapToLeader.GetProperty("x").GetInt32(), driverGapToLeader.GetProperty("y").GetInt32());
|
||||
|
||||
var driverLapTime = windows[0].GetProperty("LapTime");
|
||||
Size driverLapTimeArea = new Size(driverLapTime.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverLapTimePosition = new Point(driverLapTime.GetProperty("x").GetInt32(), driverLapTime.GetProperty("y").GetInt32());
|
||||
|
||||
|
||||
var driverDrs = windows[0].GetProperty("DRS");
|
||||
Size driverDrsArea = new Size(driverDrs.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverDrsPosition = new Point(driverDrs.GetProperty("x").GetInt32(), driverDrs.GetProperty("y").GetInt32());
|
||||
|
||||
var driverTyres = windows[0].GetProperty("Tyres");
|
||||
Size driverTyresArea = new Size(driverTyres.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverTyresPosition = new Point(driverTyres.GetProperty("x").GetInt32(), driverTyres.GetProperty("y").GetInt32());
|
||||
|
||||
var driverName = windows[0].GetProperty("Name");
|
||||
Size driverNameArea = new Size(driverName.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverNamePosition = new Point(driverName.GetProperty("x").GetInt32(), driverName.GetProperty("y").GetInt32());
|
||||
|
||||
var driverSector1 = windows[0].GetProperty("Sector1");
|
||||
Size driverSector1Area = new Size(driverSector1.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverSector1Position = new Point(driverSector1.GetProperty("x").GetInt32(), driverSector1.GetProperty("y").GetInt32());
|
||||
|
||||
var driverSector2 = windows[0].GetProperty("Sector2");
|
||||
Size driverSector2Area = new Size(driverSector2.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverSector2Position = new Point(driverSector2.GetProperty("x").GetInt32(), driverSector2.GetProperty("y").GetInt32());
|
||||
|
||||
var driverSector3 = windows[0].GetProperty("Sector3");
|
||||
Size driverSector3Area = new Size(driverSector3.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverSector3Position = new Point(driverSector3.GetProperty("x").GetInt32(), driverSector3.GetProperty("y").GetInt32());
|
||||
|
||||
float offset = (((float)mainZone.ZoneImage.Height - (float)(driverListToFill.Count * FirstZoneSize.Height)) / (float)driverListToFill.Count);
|
||||
Bitmap MainZoneImage = mainZone.ZoneImage;
|
||||
List<Zone> zonesToAdd = new List<Zone>();
|
||||
List<Bitmap> zonesImages = new List<Bitmap>();
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_DRIVERS; i++)
|
||||
{
|
||||
Point tmpPos = new Point(0, FirstZonePosition.Y + i * FirstZoneSize.Height - Convert.ToInt32(i * offset));
|
||||
Zone newDriverZone = new Zone(MainZoneImage, new Rectangle(tmpPos, FirstZoneSize), "DriverZone");
|
||||
zonesToAdd.Add(newDriverZone);
|
||||
zonesImages.Add(newDriverZone.ZoneImage);
|
||||
|
||||
newDriverZone.ZoneImage.Save("Driver"+i+".png");
|
||||
}
|
||||
|
||||
//Parallel.For(0, NUMBER_OF_DRIVERS, i =>
|
||||
for (int i = 0; i < NUMBER_OF_DRIVERS; i++)
|
||||
{
|
||||
Zone newDriverZone = zonesToAdd[(int)i];
|
||||
Bitmap zoneImg = zonesImages[(int)i];
|
||||
|
||||
newDriverZone.AddWindow(new DriverPositionWindow(zoneImg, new Rectangle(driverPositionPosition, driverPositionArea),LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverGapToLeaderWindow(zoneImg, new Rectangle(driverGapToLeaderPosition, driverGapToLeaderArea), LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverLapTimeWindow(zoneImg, new Rectangle(driverLapTimePosition, driverLapTimeArea), LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverDrsWindow(zoneImg, new Rectangle(driverDrsPosition, driverDrsArea), LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverTyresWindow(zoneImg, new Rectangle(driverTyresPosition, driverTyresArea), LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverNameWindow(zoneImg, new Rectangle(driverNamePosition, driverNameArea), LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverSectorWindow(zoneImg, new Rectangle(driverSector1Position, driverSector1Area),1, LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverSectorWindow(zoneImg, new Rectangle(driverSector2Position, driverSector2Area),2, LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverSectorWindow(zoneImg, new Rectangle(driverSector3Position, driverSector3Area),3, LoadOCR));
|
||||
|
||||
mainZone.AddZone(newDriverZone);
|
||||
}//);
|
||||
//MessageBox.Show("We have a main zone with " + MainZone.Zones.Count() + " Driver zones with " + MainZone.Zones[4].Windows.Count() + " windows each and we have " + Drivers.Count + " drivers");
|
||||
mainZones.Add(mainZone);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
MessageBox.Show("Error reading JSON file: " + ex.Message);
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
MessageBox.Show("Invalid JSON format: " + ex.Message);
|
||||
}
|
||||
return mainZones;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that calls all the zones and windows to get the content they can find on the image to display them
|
||||
/// </summary>
|
||||
/// <param name="idImage">The id of the image we are working with</param>
|
||||
/// <returns>a string representation of all the returns</returns>
|
||||
public async Task<string> Decode(List<Zone> mainZones,List<string> drivers)
|
||||
{
|
||||
string result = "";
|
||||
List<DriverData> mainResults = new List<DriverData>();
|
||||
|
||||
//Decode
|
||||
for (int mainZoneId = 0; mainZoneId < mainZones.Count; mainZoneId++)
|
||||
{
|
||||
switch (mainZoneId)
|
||||
{
|
||||
case 0:
|
||||
//Main Zone
|
||||
foreach (Zone z in mainZones[mainZoneId].Zones)
|
||||
{
|
||||
mainResults.Add(await z.Decode(Drivers));
|
||||
}
|
||||
break;
|
||||
//Next there could be a Title Zone and TrackInfoZone
|
||||
}
|
||||
}
|
||||
|
||||
//Display
|
||||
foreach (DriverData driver in mainResults)
|
||||
{
|
||||
result += driver.ToString();
|
||||
result += Environment.NewLine;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that can be used to convert an amount of miliseconds into a more readable human form
|
||||
/// </summary>
|
||||
/// <param name="amountOfMs">The given amount of miliseconds ton convert</param>
|
||||
/// <returns>A human readable string that represents the ms</returns>
|
||||
public static string ConvertMsToTime(int amountOfMs)
|
||||
{
|
||||
//Convert.ToInt32 would round upand I dont want that
|
||||
int minuts = (int)((float)amountOfMs / (1000f * 60f));
|
||||
int seconds = (int)((amountOfMs - (minuts * 60f * 1000f)) / 1000);
|
||||
int ms = amountOfMs - ((minuts * 60 * 1000) + (seconds * 1000));
|
||||
|
||||
return minuts + ":" + seconds.ToString("00") + ":" + ms.ToString("000");
|
||||
}
|
||||
/// <summary>
|
||||
/// Old method that can draw on an image where the windows and zones are created. mostly used for debugging
|
||||
/// </summary>
|
||||
/// <param name="idImage">the #id of the image we are working with</param>
|
||||
/// <returns>the drawed bitmap</returns>
|
||||
public Bitmap Draw(Bitmap image,List<Zone> mainZones)
|
||||
{
|
||||
|
||||
Graphics g = Graphics.FromImage(image);
|
||||
|
||||
foreach (Zone z in mainZones)
|
||||
{
|
||||
int count = 0;
|
||||
foreach (Zone zz in z.Zones)
|
||||
{
|
||||
g.DrawRectangle(Pens.Red, z.Bounds);
|
||||
foreach (Window w in zz.Windows)
|
||||
{
|
||||
g.DrawRectangle(Pens.Blue, new Rectangle(z.Bounds.X + zz.Bounds.X, z.Bounds.Y + zz.Bounds.Y, zz.Bounds.Width, zz.Bounds.Height));
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public partial class Settings : Form
|
||||
{
|
||||
private string _grandPrixUrl = "";
|
||||
private string _grandPrixName = "";
|
||||
private int _grandPrixYear = 2000;
|
||||
private List<string> _driverList = new List<string>();
|
||||
|
||||
private F1TVEmulator Emulator = null;
|
||||
private ConfigurationTool Config = null;
|
||||
|
||||
private bool CreatingZone = false;
|
||||
private Point ZoneP1;
|
||||
private Point ZoneP2;
|
||||
|
||||
private bool CreatingWindow = false;
|
||||
private Point WindowP1;
|
||||
private Point WindowP2;
|
||||
|
||||
List<Rectangle> WindowsToAdd = new List<Rectangle>();
|
||||
|
||||
public string GrandPrixUrl { get => _grandPrixUrl; private set => _grandPrixUrl = value; }
|
||||
public string GrandPrixName { get => _grandPrixName; private set => _grandPrixName = value; }
|
||||
public int GrandPrixYear { get => _grandPrixYear; private set => _grandPrixYear = value; }
|
||||
public List<string> DriverList { get => _driverList; private set => _driverList = value; }
|
||||
|
||||
public Settings()
|
||||
{
|
||||
InitializeComponent();
|
||||
Load();
|
||||
}
|
||||
private void Load()
|
||||
{
|
||||
RefreshUI();
|
||||
}
|
||||
private void RefreshUI()
|
||||
{
|
||||
|
||||
lsbDrivers.DataSource = null;
|
||||
lsbDrivers.DataSource = DriverList;
|
||||
|
||||
if (Directory.Exists(ConfigurationTool.CONFIGS_FOLDER_NAME))
|
||||
{
|
||||
lsbPresets.DataSource = null;
|
||||
lsbPresets.DataSource = Directory.GetFiles(ConfigurationTool.CONFIGS_FOLDER_NAME);
|
||||
}
|
||||
if (CreatingZone)
|
||||
{
|
||||
if (ZoneP1 == new Point(-1, -1))
|
||||
{
|
||||
lblZonePointsRemaning.Text = "2 points Remaining";
|
||||
}
|
||||
else
|
||||
{
|
||||
lblZonePointsRemaning.Text = "1 point Remaining";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lblZonePointsRemaning.Text = "";
|
||||
}
|
||||
|
||||
if (CreatingWindow)
|
||||
{
|
||||
if (WindowP1 == new Point(-1, -1))
|
||||
{
|
||||
lblWindowPointsRemaining.Text = "2 points Remaining";
|
||||
}
|
||||
else
|
||||
{
|
||||
lblWindowPointsRemaining.Text = "1 point Remaining";
|
||||
}
|
||||
lblWindowPointsRemaining.Text = ConfigurationTool.NUMBER_OF_ZONES - WindowsToAdd.Count() + " Windows remaining";
|
||||
}
|
||||
else
|
||||
{
|
||||
lblWindowPointsRemaining.Text = "";
|
||||
lblWindowsRemaining.Text = "";
|
||||
}
|
||||
if (Config != null)
|
||||
{
|
||||
pbxMain.Image = Config.MainZone.Draw();
|
||||
if(Config.MainZone.Zones.Count > 0)
|
||||
pbxDriverZone.Image = Config.MainZone.Zones[0].Draw();
|
||||
}
|
||||
}
|
||||
private void CreateNewZone(Point p1, Point p2)
|
||||
{
|
||||
Rectangle dimensions = CreateAbsoluteRectangle(p1, p2);
|
||||
Config = new ConfigurationTool((Bitmap)pbxMain.Image, dimensions);
|
||||
RefreshUI();
|
||||
}
|
||||
private void CreateWindows(List<Rectangle> dimensions)
|
||||
{
|
||||
if (Config != null)
|
||||
{
|
||||
Config.AddWindows(dimensions);
|
||||
}
|
||||
}
|
||||
private void tbxGpUrl_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
GrandPrixUrl = tbxGpUrl.Text;
|
||||
}
|
||||
|
||||
private void tbxGpName_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
GrandPrixName = tbxGpName.Text;
|
||||
}
|
||||
|
||||
private void tbxGpYear_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
int year;
|
||||
try
|
||||
{
|
||||
year = Convert.ToInt32(tbxGpYear.Text);
|
||||
}
|
||||
catch
|
||||
{
|
||||
year = 1545;
|
||||
}
|
||||
GrandPrixYear = year;
|
||||
}
|
||||
|
||||
private void btnAddDriver_Click(object sender, EventArgs e)
|
||||
{
|
||||
string newDriver = tbxDriverName.Text;
|
||||
DriverList.Add(newDriver);
|
||||
tbxDriverName.Text = "";
|
||||
RefreshUI();
|
||||
}
|
||||
|
||||
private void btnRemoveDriver_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (lsbDrivers.SelectedIndex >= 0)
|
||||
{
|
||||
DriverList.RemoveAt(lsbDrivers.SelectedIndex);
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
private void SwitchZoneCreation()
|
||||
{
|
||||
if (CreatingZone)
|
||||
{
|
||||
CreatingZone = false;
|
||||
lblZonePointsRemaning.Text = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
CreatingZone = true;
|
||||
|
||||
if (Config != null)
|
||||
Config.ResetMainZone();
|
||||
|
||||
if (CreatingWindow)
|
||||
SwitchWindowCreation();
|
||||
|
||||
if (Emulator != null && Emulator.Ready)
|
||||
{
|
||||
Config = null;
|
||||
pbxMain.Image = Emulator.Screenshot();
|
||||
}
|
||||
|
||||
ZoneP1 = new Point(-1, -1);
|
||||
ZoneP2 = new Point(-1, -1);
|
||||
|
||||
lblZonePointsRemaning.Text = "2 Points left";
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
private void SwitchWindowCreation()
|
||||
{
|
||||
if (CreatingWindow)
|
||||
{
|
||||
CreatingWindow = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreatingWindow = true;
|
||||
|
||||
if (Config != null)
|
||||
Config.ResetWindows();
|
||||
|
||||
if (CreatingZone)
|
||||
SwitchZoneCreation();
|
||||
|
||||
WindowP1 = new Point(-1, -1);
|
||||
WindowP2 = new Point(-1, -1);
|
||||
|
||||
WindowsToAdd = new List<Rectangle>();
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
private void btnCreatZone_Click(object sender, EventArgs e)
|
||||
{
|
||||
SwitchZoneCreation();
|
||||
}
|
||||
private void btnCreateWindow_Click(object sender, EventArgs e)
|
||||
{
|
||||
SwitchWindowCreation();
|
||||
}
|
||||
private void pbxMain_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (CreatingZone && pbxMain.Image != null)
|
||||
{
|
||||
//Point coordinates = pbxMain.PointToClient(new Point(MousePosition.X, MousePosition.Y));
|
||||
Point coordinates = e.Location;
|
||||
float xOffset = (float)pbxMain.Image.Width / (float)pbxMain.Width;
|
||||
float yOffset = (float)pbxMain.Image.Height / (float)pbxMain.Height;
|
||||
Point newPoint = new Point(Convert.ToInt32((float)coordinates.X * xOffset), Convert.ToInt32((float)coordinates.Y * yOffset));
|
||||
|
||||
//MessageBox.Show("Coordinates" + Environment.NewLine + "Old : " + coordinates.ToString() + Environment.NewLine + "New : " + newPoint.ToString());
|
||||
|
||||
if (ZoneP1 == new Point(-1, -1))
|
||||
{
|
||||
ZoneP1 = newPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZoneP2 = newPoint;
|
||||
CreateNewZone(ZoneP1, ZoneP2);
|
||||
SwitchZoneCreation();
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
}
|
||||
private void pbxMain_Click(object sender, EventArgs e)
|
||||
{
|
||||
//Not the right one to use visibly
|
||||
}
|
||||
private void pbxDriverZone_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (CreatingWindow && pbxDriverZone.Image != null)
|
||||
{
|
||||
Point coordinates = e.Location;
|
||||
|
||||
float xOffset = (float)pbxDriverZone.Image.Width / (float)pbxDriverZone.Width;
|
||||
float yOffset = (float)pbxDriverZone.Image.Height / (float)pbxDriverZone.Height;
|
||||
|
||||
Point newPoint = new Point(Convert.ToInt32((float)coordinates.X * xOffset), Convert.ToInt32((float)coordinates.Y * yOffset));
|
||||
|
||||
if (WindowP1 == new Point(-1, -1))
|
||||
{
|
||||
WindowP1 = newPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowP2 = newPoint;
|
||||
WindowsToAdd.Add(CreateAbsoluteRectangle(WindowP1, WindowP2));
|
||||
|
||||
if (WindowsToAdd.Count < ConfigurationTool.NUMBER_OF_ZONES)
|
||||
{
|
||||
WindowP1 = new Point(-1, -1);
|
||||
WindowP2 = new Point(-1, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowP1 = new Point(WindowP1.X, 0);
|
||||
WindowP2 = new Point(WindowP2.X, pbxDriverZone.Image.Height);
|
||||
CreateWindows(WindowsToAdd);
|
||||
SwitchWindowCreation();
|
||||
}
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
}
|
||||
private void pbxDriverZone_Click(object sender, EventArgs e)
|
||||
{
|
||||
//Not the right one to use visibly
|
||||
}
|
||||
private Rectangle CreateAbsoluteRectangle(Point p1, Point p2)
|
||||
{
|
||||
Point newP1 = new Point();
|
||||
Point newP2 = new Point();
|
||||
|
||||
if (p1.X < p2.X)
|
||||
{
|
||||
newP1.X = p1.X;
|
||||
newP2.X = p2.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
newP1.X = p2.X;
|
||||
newP2.X = p1.X;
|
||||
}
|
||||
|
||||
if (p1.Y < p2.Y)
|
||||
{
|
||||
newP1.Y = p1.Y;
|
||||
newP2.Y = p2.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
newP1.Y = p2.Y;
|
||||
newP2.Y = p1.Y;
|
||||
}
|
||||
return new Rectangle(newP1.X, newP1.Y, newP2.X - newP1.X, newP2.Y - newP1.Y);
|
||||
}
|
||||
|
||||
private async void btnRefresh_Click(object sender, EventArgs e)
|
||||
{
|
||||
btnRefresh.Enabled = false;
|
||||
if (Emulator == null || Emulator.GrandPrixUrl != tbxGpUrl.Text)
|
||||
{
|
||||
Emulator = new F1TVEmulator(tbxGpUrl.Text);
|
||||
}
|
||||
|
||||
if (!Emulator.Ready)
|
||||
{
|
||||
Task<int> start = Task.Run(() => Emulator.Start());
|
||||
int errorCode = await start;
|
||||
if (errorCode != 0)
|
||||
{
|
||||
string message;
|
||||
switch (errorCode)
|
||||
{
|
||||
case 101:
|
||||
message = "Error " + errorCode + " Could not start the driver. It could be because an other instance is runnin make sure you closed them all before trying again";
|
||||
break;
|
||||
case 102:
|
||||
message = "Error " + errorCode + " Could not navigate on the F1TV site. Make sure the correct URL has been given and that you logged from chrome. It can take a few minutes to update";
|
||||
break;
|
||||
case 103:
|
||||
message = "Error " + errorCode + " The url is not a valid url";
|
||||
break;
|
||||
case 104:
|
||||
message = "Error " + errorCode + " The url is not a valid url";
|
||||
break;
|
||||
case 105:
|
||||
message = "Error " + errorCode + " There has been an error trying to emulate button presses. Please try again";
|
||||
break;
|
||||
case 106:
|
||||
message = "Error " + errorCode + " There has been an error trying to emulate button presses. Please try again";
|
||||
break;
|
||||
default:
|
||||
message = "Could not start the emulator Error " + errorCode;
|
||||
break;
|
||||
}
|
||||
MessageBox.Show(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
pbxMain.Image = Emulator.Screenshot();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pbxMain.Image = Emulator.Screenshot();
|
||||
}
|
||||
btnRefresh.Enabled = true;
|
||||
}
|
||||
|
||||
private void Settings_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
if (Emulator != null)
|
||||
{
|
||||
Emulator.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void btnResetDriver_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (Emulator != null)
|
||||
{
|
||||
Emulator.ResetDriver();
|
||||
}
|
||||
}
|
||||
|
||||
private void btnSavePreset_Click(object sender, EventArgs e)
|
||||
{
|
||||
string presetName = tbxPresetName.Text;
|
||||
if (Config != null)
|
||||
{
|
||||
Config.SaveToJson(DriverList,presetName);
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
|
||||
private void lsbPresets_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
//Nothing
|
||||
}
|
||||
|
||||
private void btnLoadPreset_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (lsbPresets.SelectedIndex >= 0 && pbxMain.Image != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Reader reader = new Reader(lsbPresets.Items[lsbPresets.SelectedIndex].ToString(), (Bitmap)pbxMain.Image,false);
|
||||
//MainZones #0 is the big main zone containing driver zones
|
||||
Config = new ConfigurationTool((Bitmap)pbxMain.Image, reader.MainZones[0].Bounds);
|
||||
Config.MainZone = reader.MainZones[0];
|
||||
DriverList = reader.Drivers;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Could not load the settings error :" + ex);
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : Window.cs
|
||||
/// Brief : Default Window object that is mainly expected to be inherited.
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using Tesseract;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class Window
|
||||
{
|
||||
private Rectangle _bounds;
|
||||
private Bitmap _image;
|
||||
private string _name;
|
||||
protected TesseractEngine Engine;
|
||||
public Rectangle Bounds { get => _bounds; private set => _bounds = value; }
|
||||
public Bitmap Image { get => _image; set => _image = value; }
|
||||
public string Name { get => _name; protected set => _name = value; }
|
||||
//This will have to be changed if you want to make it run on your machine
|
||||
public static DirectoryInfo TESS_DATA_FOLDER = new DirectoryInfo(@"C:\Users\Moi\Pictures\SeleniumScreens\TessData");
|
||||
|
||||
public Bitmap WindowImage
|
||||
{
|
||||
get
|
||||
{
|
||||
//This little trickery lets you have the image that the window sees
|
||||
Bitmap sample = new Bitmap(Bounds.Width, Bounds.Height);
|
||||
Graphics g = Graphics.FromImage(sample);
|
||||
g.DrawImage(Image, new Rectangle(0, 0, sample.Width, sample.Height), Bounds, GraphicsUnit.Pixel);
|
||||
return sample;
|
||||
}
|
||||
}
|
||||
public Window(Bitmap image, Rectangle bounds, bool generateEngine = true)
|
||||
{
|
||||
Image = image;
|
||||
Bounds = bounds;
|
||||
if (generateEngine)
|
||||
{
|
||||
Engine = new TesseractEngine(TESS_DATA_FOLDER.FullName, "eng", EngineMode.Default);
|
||||
Engine.DefaultPageSegMode = PageSegMode.SingleLine;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that will have to be used by the childrens to let the model make them decode the images they have
|
||||
/// </summary>
|
||||
/// <returns>Returns an object because we dont know what kind of return it will be</returns>
|
||||
public virtual async Task<Object> DecodePng()
|
||||
{
|
||||
return "NaN";
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that will have to be used by the childrens to let the model make them decode the images they have
|
||||
/// </summary>
|
||||
/// <param name="driverList">This is a list of the different possible drivers in the race. It should not be too big but NEVER be too short</param>
|
||||
/// <returns>Returns an object because we dont know what kind of return it will be</returns>
|
||||
public virtual async Task<Object> DecodePng(List<string> driverList)
|
||||
{
|
||||
return "NaN";
|
||||
}
|
||||
/// <summary>
|
||||
/// This converts an image into a byte[]. It can be usefull when doing unsafe stuff. Use at your own risks
|
||||
/// </summary>
|
||||
/// <param name="inputImage">The image you want to convert</param>
|
||||
/// <returns>A byte array containing the image informations</returns>
|
||||
public static byte[] ImageToByte(Image inputImage)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
inputImage.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// This method is used to recover a time from a PNG using Tesseract OCR
|
||||
/// </summary>
|
||||
/// <param name="windowImage">The image where the text is</param>
|
||||
/// <param name="windowType">The type of window it is</param>
|
||||
/// <param name="Engine">The Tesseract Engine</param>
|
||||
/// <returns>The time in milliseconds</returns>
|
||||
public static async Task<int> GetTimeFromPng(Bitmap windowImage, OcrImage.WindowType windowType, TesseractEngine Engine)
|
||||
{
|
||||
//Kind of a big method but it has a lot of error handling and has to work with three special cases
|
||||
string rawResult = "";
|
||||
int result = 0;
|
||||
|
||||
switch (windowType)
|
||||
{
|
||||
case OcrImage.WindowType.Sector:
|
||||
//The usual sector is in this form : 33.456
|
||||
Engine.SetVariable("tessedit_char_whitelist", "0123456789.");
|
||||
break;
|
||||
case OcrImage.WindowType.LapTime:
|
||||
//The usual Lap time is in this form : 1:45:345
|
||||
Engine.SetVariable("tessedit_char_whitelist", "0123456789.:");
|
||||
break;
|
||||
case OcrImage.WindowType.Gap:
|
||||
//The usual Gap is in this form : + 34.567
|
||||
Engine.SetVariable("tessedit_char_whitelist", "0123456789.+");
|
||||
break;
|
||||
default:
|
||||
Engine.SetVariable("tessedit_char_whitelist", "");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Bitmap enhancedImage = new OcrImage(windowImage).Enhance(windowType);
|
||||
|
||||
var tessImage = Pix.LoadFromMemory(ImageToByte(enhancedImage));
|
||||
|
||||
Page page = Engine.Process(tessImage);
|
||||
Graphics g = Graphics.FromImage(enhancedImage);
|
||||
// Get the iterator for the page layout
|
||||
using (var iter = page.GetIterator())
|
||||
{
|
||||
// Loop over the elements of the page layout
|
||||
iter.Begin();
|
||||
do
|
||||
{
|
||||
// Get the text for the current element
|
||||
try
|
||||
{
|
||||
rawResult += iter.GetText(PageIteratorLevel.Word);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//nothing we just dont add it if its not a number
|
||||
}
|
||||
} while (iter.Next(PageIteratorLevel.Word));
|
||||
}
|
||||
|
||||
List<string> rawNumbers;
|
||||
|
||||
//In the gaps we can find '+' but we dont care about it its redondant a driver will never be - something
|
||||
if (windowType == OcrImage.WindowType.Gap)
|
||||
rawResult = Regex.Replace(rawResult, "[^0-9.:]", "");
|
||||
|
||||
//Splits into minuts seconds miliseconds
|
||||
rawNumbers = rawResult.Split('.', ':').ToList<string>();
|
||||
//removes any empty cells (tho this usually sign of a really bad OCR implementation tbh will have to be fixed higher in the chian)
|
||||
rawNumbers.RemoveAll(x => ((string)x) == "");
|
||||
|
||||
if (rawNumbers.Count == 3)
|
||||
{
|
||||
//mm:ss:ms
|
||||
result = (Convert.ToInt32(rawNumbers[0]) * 1000 * 60) + (Convert.ToInt32(rawNumbers[1]) * 1000) + Convert.ToInt32(rawNumbers[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rawNumbers.Count == 2)
|
||||
{
|
||||
//ss:ms
|
||||
result = (Convert.ToInt32(rawNumbers[0]) * 1000) + Convert.ToInt32(rawNumbers[1]);
|
||||
|
||||
if (result > 999999)
|
||||
{
|
||||
//We know that we have way too much seconds to make a minut
|
||||
//Its usually because the ":" have been interpreted as a number
|
||||
int minuts = (int)(rawNumbers[0][0] - '0');
|
||||
// rawNumbers[0][1] should contain the : that has been mistaken
|
||||
int seconds = Convert.ToInt32(rawNumbers[0][2].ToString() + rawNumbers[0][3].ToString());
|
||||
int ms = Convert.ToInt32(rawNumbers[1]);
|
||||
result = (Convert.ToInt32(minuts) * 1000 * 60) + (Convert.ToInt32(seconds) * 1000) + Convert.ToInt32(ms);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rawNumbers.Count == 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = Convert.ToInt32(rawNumbers[0]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//It can be because the input is empty or because its the LEADER bracket
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Auuuugh
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
page.Dispose();
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that recovers strings from an image using Tesseract OCR
|
||||
/// </summary>
|
||||
/// <param name="WindowImage">The image of the window that contains text</param>
|
||||
/// <param name="Engine">The Tesseract engine</param>
|
||||
/// <param name="allowedChars">The list of allowed chars</param>
|
||||
/// <param name="windowType">The type of window the text is on. Depending on the context the OCR will behave differently</param>
|
||||
/// <returns>the string it found</returns>
|
||||
public static async Task<string> GetStringFromPng(Bitmap WindowImage, TesseractEngine Engine, string allowedChars = "", OcrImage.WindowType windowType = OcrImage.WindowType.Text)
|
||||
{
|
||||
string result = "";
|
||||
|
||||
Engine.SetVariable("tessedit_char_whitelist", allowedChars);
|
||||
|
||||
Bitmap rawData = WindowImage;
|
||||
Bitmap enhancedImage = new OcrImage(rawData).Enhance(windowType);
|
||||
|
||||
Page page = Engine.Process(enhancedImage);
|
||||
using (var iter = page.GetIterator())
|
||||
{
|
||||
iter.Begin();
|
||||
do
|
||||
{
|
||||
result += iter.GetText(PageIteratorLevel.Word);
|
||||
} while (iter.Next(PageIteratorLevel.Word));
|
||||
}
|
||||
page.Dispose();
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Get a smaller image from a bigger one
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The big bitmap you want to get a part of</param>
|
||||
/// <param name="newBitmapDimensions">The dimensions of the new bitmap</param>
|
||||
/// <returns>The little bitmap</returns>
|
||||
protected Bitmap GetSmallBitmapFromBigOne(Bitmap inputBitmap, Rectangle newBitmapDimensions)
|
||||
{
|
||||
Bitmap sample = new Bitmap(newBitmapDimensions.Width, newBitmapDimensions.Height);
|
||||
Graphics g = Graphics.FromImage(sample);
|
||||
g.DrawImage(inputBitmap, new Rectangle(0, 0, sample.Width, sample.Height), newBitmapDimensions, GraphicsUnit.Pixel);
|
||||
return sample;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the closest string from a list of options
|
||||
/// </summary>
|
||||
/// <param name="options">an array of all the possibilities</param>
|
||||
/// <param name="testString">the string you want to compare</param>
|
||||
/// <returns>The closest option</returns>
|
||||
protected static string FindClosestMatch(List<string> options, string testString)
|
||||
{
|
||||
var closestMatch = "";
|
||||
var closestDistance = int.MaxValue;
|
||||
|
||||
foreach (var item in options)
|
||||
{
|
||||
var distance = LevenshteinDistance(item, testString);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestMatch = item;
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
return closestMatch;
|
||||
}
|
||||
//This method has been generated with the help of ChatGPT
|
||||
/// <summary>
|
||||
/// Method that computes a score of distance between two strings
|
||||
/// </summary>
|
||||
/// <param name="string1">The first string (order irrelevant)</param>
|
||||
/// <param name="string2">The second string (order irrelevant)</param>
|
||||
/// <returns>The levenshtein distance</returns>
|
||||
protected static int LevenshteinDistance(string string1, string string2)
|
||||
{
|
||||
if (string.IsNullOrEmpty(string1))
|
||||
{
|
||||
return string.IsNullOrEmpty(string2) ? 0 : string2.Length;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(string2))
|
||||
{
|
||||
return string.IsNullOrEmpty(string1) ? 0 : string1.Length;
|
||||
}
|
||||
|
||||
var d = new int[string1.Length + 1, string2.Length + 1];
|
||||
for (var i = 0; i <= string1.Length; i++)
|
||||
{
|
||||
d[i, 0] = i;
|
||||
}
|
||||
|
||||
for (var j = 0; j <= string2.Length; j++)
|
||||
{
|
||||
d[0, j] = j;
|
||||
}
|
||||
|
||||
for (var i = 1; i <= string1.Length; i++)
|
||||
{
|
||||
for (var j = 1; j <= string2.Length; j++)
|
||||
{
|
||||
var cost = (string1[i - 1] == string2[j - 1]) ? 0 : 1;
|
||||
d[i, j] = Math.Min(Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost);
|
||||
}
|
||||
}
|
||||
|
||||
return d[string1.Length, string2.Length];
|
||||
}
|
||||
public virtual string ToJSON()
|
||||
{
|
||||
string result = "";
|
||||
|
||||
result += "\"" + Name + "\"" + ":{" + Environment.NewLine;
|
||||
result += "\t" + "\"x\":" + Bounds.X + "," + Environment.NewLine;
|
||||
result += "\t" + "\"y\":" + Bounds.Y + "," + Environment.NewLine;
|
||||
result += "\t" + "\"width\":" + Bounds.Width + Environment.NewLine;
|
||||
result += "}";
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : Zone.cs
|
||||
/// Brief : Class that contains all the methods and infos for a zone. This is designed to be potentially be inherited.
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class Zone
|
||||
{
|
||||
private Rectangle _bounds;
|
||||
private List<Zone> _zones;
|
||||
private List<Window> _windows;
|
||||
private Bitmap _image;
|
||||
private string _name;
|
||||
|
||||
public Bitmap ZoneImage
|
||||
{
|
||||
get
|
||||
{
|
||||
//This little trickery lets you have the image that the zone sees
|
||||
Bitmap sample = new Bitmap(Bounds.Width, Bounds.Height);
|
||||
Graphics g = Graphics.FromImage(sample);
|
||||
g.DrawImage(Image, new Rectangle(0, 0, sample.Width, sample.Height), Bounds, GraphicsUnit.Pixel);
|
||||
return sample;
|
||||
}
|
||||
}
|
||||
public Bitmap Image
|
||||
{
|
||||
get { return _image; }
|
||||
set
|
||||
{
|
||||
//It automatically sets the image for the contained windows and zones
|
||||
_image = Image;
|
||||
foreach (Window w in Windows)
|
||||
{
|
||||
w.Image = ZoneImage;
|
||||
}
|
||||
foreach (Zone z in Zones)
|
||||
{
|
||||
z.Image = Image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle Bounds { get => _bounds; protected set => _bounds = value; }
|
||||
public List<Zone> Zones { get => _zones; protected set => _zones = value; }
|
||||
public List<Window> Windows { get => _windows; protected set => _windows = value; }
|
||||
public string Name { get => _name; protected set => _name = value; }
|
||||
|
||||
public Zone(Bitmap image, Rectangle bounds, string name)
|
||||
{
|
||||
Windows = new List<Window>();
|
||||
Zones = new List<Zone>();
|
||||
Name = name;
|
||||
|
||||
//You cant set the image in the CTOR because the processing is impossible at first initiation
|
||||
_image = image;
|
||||
Bounds = bounds;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a zone to the list of zones
|
||||
/// </summary>
|
||||
/// <param name="zone">The zone you want to add</param>
|
||||
public virtual void AddZone(Zone zone)
|
||||
{
|
||||
Zones.Add(zone);
|
||||
}
|
||||
/// <summary>
|
||||
/// Add a window to the list of windows
|
||||
/// </summary>
|
||||
/// <param name="window">the window you want to add</param>
|
||||
public virtual void AddWindow(Window window)
|
||||
{
|
||||
Windows.Add(window);
|
||||
}
|
||||
/// <summary>
|
||||
/// Calls all the windows to do OCR and to give back the results so we can send them to the model
|
||||
/// </summary>
|
||||
/// <param name="driverList">A list of all the driver in the race to help with text recognition</param>
|
||||
/// <returns>A driver data object that contains all the infos about a driver</returns>
|
||||
public virtual async Task<DriverData> Decode(List<string> driverList)
|
||||
{
|
||||
int sectorCount = 0;
|
||||
DriverData result = new DriverData();
|
||||
Parallel.ForEach(Windows, async w =>
|
||||
{
|
||||
// A switch would be prettier but I dont think its supported in this C# version
|
||||
if (w is DriverNameWindow)
|
||||
result.Name = (string)await (w as DriverNameWindow).DecodePng(driverList);
|
||||
if (w is DriverDrsWindow)
|
||||
result.DRS = (bool)await (w as DriverDrsWindow).DecodePng();
|
||||
if (w is DriverGapToLeaderWindow)
|
||||
result.GapToLeader = (int)await (w as DriverGapToLeaderWindow).DecodePng();
|
||||
if (w is DriverLapTimeWindow)
|
||||
result.LapTime = (int)await (w as DriverLapTimeWindow).DecodePng();
|
||||
if (w is DriverPositionWindow)
|
||||
result.Position = (int)await (w as DriverPositionWindow).DecodePng();
|
||||
if (w is DriverSectorWindow)
|
||||
{
|
||||
sectorCount++;
|
||||
if (sectorCount == 1)
|
||||
result.Sector1 = (int)await (w as DriverSectorWindow).DecodePng();
|
||||
if (sectorCount == 2)
|
||||
result.Sector2 = (int)await (w as DriverSectorWindow).DecodePng();
|
||||
if (sectorCount == 3)
|
||||
result.Sector3 = (int)await (w as DriverSectorWindow).DecodePng();
|
||||
}
|
||||
if (w is DriverTyresWindow)
|
||||
result.CurrentTyre = (Tyre)await (w as DriverTyresWindow).DecodePng();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
public virtual Bitmap Draw()
|
||||
{
|
||||
Bitmap img;
|
||||
|
||||
//If its the main zone we want to see everything
|
||||
if (Zones.Count > 0)
|
||||
{
|
||||
img = Image;
|
||||
}
|
||||
else
|
||||
{
|
||||
img = ZoneImage;
|
||||
}
|
||||
|
||||
Graphics g = Graphics.FromImage(img);
|
||||
|
||||
//If its the main zone we need to visualize the Zone bounds displayed
|
||||
if (Zones.Count > 0)
|
||||
g.DrawRectangle(new Pen(Brushes.Violet, 5), Bounds);
|
||||
|
||||
foreach (Zone z in Zones)
|
||||
{
|
||||
Rectangle newBounds = new Rectangle(z.Bounds.X, z.Bounds.Y + Bounds.Y, z.Bounds.Width, z.Bounds.Height);
|
||||
g.DrawRectangle(Pens.Red, newBounds);
|
||||
}
|
||||
foreach (Window w in Windows)
|
||||
{
|
||||
g.DrawRectangle(Pens.Blue, w.Bounds);
|
||||
}
|
||||
return img;
|
||||
}
|
||||
public void ResetZones()
|
||||
{
|
||||
Zones.Clear();
|
||||
}
|
||||
public void ResetWindows()
|
||||
{
|
||||
foreach (Zone z in Zones)
|
||||
{
|
||||
z.ResetWindows();
|
||||
}
|
||||
Windows.Clear();
|
||||
}
|
||||
public virtual string ToJSON()
|
||||
{
|
||||
string result = "";
|
||||
result += "\"" + Name + "\":{" + Environment.NewLine;
|
||||
result += "\t" + "\"x\":" + Bounds.X + "," + Environment.NewLine;
|
||||
result += "\t" + "\"y\":" + Bounds.Y + "," + Environment.NewLine;
|
||||
result += "\t" + "\"width\":" + Bounds.Width + "," + Environment.NewLine;
|
||||
result += "\t" + "\"height\":" + Bounds.Height;
|
||||
|
||||
if (Windows.Count != 0)
|
||||
{
|
||||
result += "," + Environment.NewLine;
|
||||
|
||||
result += "\t" + "\"Windows\":[" + Environment.NewLine;
|
||||
result += "\t\t{" + Environment.NewLine;
|
||||
int Wcount = 0;
|
||||
foreach (Window w in Windows)
|
||||
{
|
||||
result += "\t\t" + w.ToJSON();
|
||||
Wcount++;
|
||||
if (Wcount != Windows.Count)
|
||||
result += ",";
|
||||
}
|
||||
result += "\t\t}" + Environment.NewLine;
|
||||
result += "\t" + "]" + Environment.NewLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += Environment.NewLine;
|
||||
}
|
||||
if (Zones.Count != 0)
|
||||
{
|
||||
result += "," + Environment.NewLine;
|
||||
|
||||
result += "\t" + "\"Zones\":[" + Environment.NewLine;
|
||||
result += "\t\t{" + Environment.NewLine;
|
||||
int Zcount = 0;
|
||||
//foreach (Zone z in Zones)
|
||||
//{
|
||||
result += "\t\t" + Zones[0].ToJSON();
|
||||
Zcount++;
|
||||
if (Zcount != Zones.Count)
|
||||
//result += ",";
|
||||
//}
|
||||
result += "\t\t}" + Environment.NewLine;
|
||||
result += "\t" + "]" + Environment.NewLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += Environment.NewLine;
|
||||
}
|
||||
|
||||
result += "}";
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Checks if the given Rectangle fits in the current zone
|
||||
/// </summary>
|
||||
/// <param name="InputRectangle">The Rectangle you want to check the fittment</param>
|
||||
/// <returns></returns>
|
||||
protected bool Fits(Rectangle inputRectangle)
|
||||
{
|
||||
if (inputRectangle.X + inputRectangle.Width > Bounds.Width || inputRectangle.Y + inputRectangle.Height > Bounds.Height || inputRectangle.X < 0 || inputRectangle.Y < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
# Rohmer Maxime
|
||||
# RecoverCookies.py
|
||||
# Little script that recovers the cookies stored in the chrome sqlite database and then decrypts them using the key stored in the chrome files
|
||||
# This script has been created to be used by an other programm or for the data to not be used directly. This is why it stores all the decoded cookies in a csv. (Btw could be smart for the end programm to delete the csv after using it)
|
||||
# Parts of this cript have been created with the help of ChatGPT
|
||||
|
||||
import os
|
||||
import json
|
||||
import base64
|
||||
import sqlite3
|
||||
import win32crypt
|
||||
from Cryptodome.Cipher import AES
|
||||
from pathlib import Path
|
||||
import csv
|
||||
|
||||
def get_master_key():
|
||||
with open(
|
||||
os.getenv("localappdata") + "\\Google\\Chrome\\User Data\\Local State", "r"
|
||||
) as f:
|
||||
local_state = f.read()
|
||||
local_state = json.loads(local_state)
|
||||
master_key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
|
||||
master_key = master_key[5:] # removing DPAPI
|
||||
master_key = win32crypt.CryptUnprotectData(master_key, None, None, None, 0)[1]
|
||||
print("MASTER KEY :")
|
||||
print(master_key)
|
||||
print(len(master_key))
|
||||
return master_key
|
||||
|
||||
def decrypt_payload(cipher, payload):
|
||||
return cipher.decrypt(payload)
|
||||
|
||||
def generate_cipher(aes_key, iv):
|
||||
return AES.new(aes_key, AES.MODE_GCM, iv)
|
||||
|
||||
def decrypt_password(buff, master_key):
|
||||
try:
|
||||
iv = buff[3:15]
|
||||
payload = buff[15:]
|
||||
cipher = generate_cipher(master_key, iv)
|
||||
decrypted_pass = decrypt_payload(cipher, payload)
|
||||
decrypted_pass = decrypted_pass[:-16].decode() # remove suffix bytes
|
||||
return decrypted_pass
|
||||
except Exception:
|
||||
# print("Probably saved password from Chrome version older than v80\n")
|
||||
# print(str(e))
|
||||
return "Chrome < 80"
|
||||
|
||||
|
||||
master_key = get_master_key()
|
||||
|
||||
cookies_path = Path(
|
||||
os.getenv("localappdata") + "\\Google\\Chrome\\User Data\\Default\\Network\\Cookies"
|
||||
)
|
||||
|
||||
if not cookies_path.exists():
|
||||
raise ValueError("Cookies file not found")
|
||||
|
||||
with sqlite3.connect(cookies_path) as connection:
|
||||
connection.row_factory = sqlite3.Row
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SELECT * FROM cookies")
|
||||
|
||||
with open('cookies.csv', 'a', newline='') as csvfile:
|
||||
fieldnames = ['host_key', 'name', 'value', 'path', 'expires_utc', 'is_secure', 'is_httponly']
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
||||
|
||||
if csvfile.tell() == 0:
|
||||
writer.writeheader()
|
||||
|
||||
for row in cursor.fetchall():
|
||||
decrypted_value = decrypt_password(row["encrypted_value"], master_key)
|
||||
writer.writerow({
|
||||
'host_key': row["host_key"],
|
||||
'name': row["name"],
|
||||
'value': decrypted_value,
|
||||
'path': row["path"],
|
||||
'expires_utc': row["expires_utc"],
|
||||
'is_secure': row["is_secure"],
|
||||
'is_httponly': row["is_httponly"]
|
||||
})
|
||||
|
||||
print("Finished CSV")
|
||||
|
Before Width: | Height: | Size: 3.9 MiB After Width: | Height: | Size: 3.9 MiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 236 KiB |
@@ -397,6 +397,8 @@ Cette option bien que complexe et difficile à implémenter propose une solution
|
||||
|
||||
Simuler un navigateur internet n'est pas forcément très difficile. Chromium par exemple offre une panoplie d'outils natifs et énormément de librairies existent permettant de facilement et en quelques lignes simuler un Google Chrome et le contrôler sans afficher son UI.
|
||||
|
||||
{: style="height:150px;width:150px"}
|
||||
|
||||
Cependant. La F1TV n'utilise pas simplement un player HTML5 basique. Elle utilise un service de streaming BitMovin qui permet de fournir un stream de bonne qualité et surtout qui implémente les DRM (Digital Right Management)
|
||||
|
||||
Cela veut dire que quand on ouvre un flux de la F1TV sur chrome et que l'on essaie de prendre une capture d'écran, le player se met en noir et ne permet pas de voir quoi que ce soit (Certaines version de Chrome le permettent pendant quelques semaines avant de bloquer à nouveau). Ce qui dans notre cas est un immense problème. Mais Firefox ne nous bloque pas de cette facon et il est donc assez facile de passer outre.
|
||||
@@ -409,6 +411,8 @@ Cependant Firefox de pas sa nature Open Source utilise "OpenH264" pour lire ces
|
||||
|
||||
Sauf que Firefox n'est pas aussi facilement émulé que chrome et cela réduit notre choix de librairies à ... Une seule... Qui est Selenium. (Il existe aussi Pupetteer C# mais j'ai rencontré énormément de soucis avec cette dernière dès que je voulais lancer une vidéo)
|
||||
|
||||
{: style="height:150px;width:150px"}
|
||||
|
||||
Mais même si la documentation est plutôt maigre parfois, c'est une bonne librairie qui permet de très bien contrôler une instance de chrome ou de Firefox.
|
||||
|
||||
#### Contrôler le navigateur
|
||||
@@ -423,12 +427,38 @@ Durant cette explication je vais parler à un moment de Cookies, ne vous en fait
|
||||
|
||||
Recette de cuisine pour récupèrer des images de la F1TV :
|
||||
|
||||
-
|
||||
1. Démarrer une instance de navigateur avec les bons arguments
|
||||
2. Ajouter les bons paramêtres pour ne pas se faire flag comme un bot
|
||||
3. Naviguer sur la page de la F1TV
|
||||
4. Ajouter les cookies de connexion pour avoir accès au contenu de la page
|
||||
5. Naviguer sur la page du Grand Prix demandé
|
||||
6. Attendre un peu que la page se charge
|
||||
7. Cliquer sur l'invite de cookies
|
||||
8. Attendre cinq secondes le temps que la page se reload
|
||||
9. Cliquer sur le bouton qui permet de passer du feed live à la DATA CHANNEL
|
||||
10. Appuyer sur Espace pour faire apparaitre le bouton d'accès au paramêtres
|
||||
11. Cliquer sur le menu déroulant des résolution
|
||||
12. Trouver l'option 1080P et la selectionner
|
||||
13. Cliquer sur le bouton qui met la vidéo en plein écran
|
||||
14. Prendre de screenshots à intervales réguliers
|
||||
|
||||
Pour faire toutes ces actions on doit récupèrer les éléments selon leur ID ou leur classe.
|
||||
|
||||
Voici un exemple qui récupère le bouton de plein écran et qui clique dessus :
|
||||
|
||||
```Csharp
|
||||
IWebElement fullScreenButton = Driver.FindElement(By.ClassName("bmpui-ui-fullscreentogglebutton"));
|
||||
fullScreenButton.Click();
|
||||
```
|
||||
|
||||
#### Récupèrer les cookies ?
|
||||
|
||||
[FINIR CETTE EXPLICATIOn]
|
||||
|
||||
#### Calibration
|
||||
|
||||
[AJOUTER EXPLICATION]
|
||||
|
||||
### OCR
|
||||
|
||||
Ici je vais parler de la seconde partie du projet qui parle du processus de reconnaissance de data sur une image du feed DATA de la F1TV.
|
||||
|
||||
@@ -2108,4 +2108,73 @@ Je ne suis pas un graphiste et ca se voit '^^.
|
||||
|
||||
Je pense que comme il me reste un peu de temps aujourd'hui, je vais faire un peu de documentation de la partie récupèration d'images. En effet, je pense que je n'aurai plus besoin de changer grand chose à ce niveau. Mais je ne ferai pas la partie analyse fonctionnelle car l'interface n'est clairement pas terminée.
|
||||
|
||||
En fait j'avais oublié mais j'ai eu un rendez vous médical du coup je n'ai pas eu trop le temps de faire la doc que je voulais. Mais au moins je pense avoir finit mon travail sur le poster et le abstract en Anglais qui sont les deux gros livrables à venir.
|
||||
En fait j'avais oublié mais j'ai eu un rendez vous médical du coup je n'ai pas eu trop le temps de faire la doc que je voulais. Mais au moins je pense avoir finit mon travail sur le poster et le abstract en Anglais qui sont les deux gros livrables à venir.
|
||||
|
||||
## Mardi 9 Mai 2023
|
||||
|
||||
Bon je viens de me rendre compte que apparemment on doit rendre l'abstract anglais, le Poster, ET LE PROJET. Je pense que mes deux jours à l'armée m'ont fait perdre un peu la notion du temps car j'avais l'impression que l'evaluation intermédiaire 1 était il y a genre moins d'une semaine.
|
||||
|
||||
Donc aujourd'hui je ne vais pas trop avancer sur le code et vraiment me focus sur la documentation de la récupèration d'images. Je pense que je vais aussi ajouter la partie calibration à la documentation. Je pense que c'est important que je prenne le temps maintenant car sinon le prof aura l'impression que ca n'a pas trop avancé depuis la dernière fois.
|
||||
|
||||
Et puis je pense que la partie calibration et récupèration d'images ne va pas trop changer et la partie calibration encore moins.
|
||||
|
||||
La partie anglaise je fais la revoir un peu mais je l'avais déja faite pendant les premiers jours alors ca devrait aller.
|
||||
|
||||
Pour le rendu il nous était demandé de fournir un fichier PDF avec tout dedans avec une table des matières notre code source etc...
|
||||
|
||||
Pour ce faire j'ai du changer le mkdocs.yml et installer des packages.
|
||||
|
||||
Voici les changements ::
|
||||
|
||||
```yml
|
||||
site_name: Documentation Track Trends
|
||||
site_author: Rohmer Maxime
|
||||
copyright: ©CFPTI Tech2
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
# Palette toggle for light mode
|
||||
- media: "(prefers-color-scheme: light)"
|
||||
scheme: default
|
||||
toggle:
|
||||
icon: material/brightness-7
|
||||
name: Switch to dark mode
|
||||
|
||||
# Palette toggle for dark mode
|
||||
- media: "(prefers-color-scheme: dark)"
|
||||
scheme: slate
|
||||
toggle:
|
||||
icon: material/brightness-4
|
||||
name: Switch to light mode
|
||||
markdown_extensions:
|
||||
- attr_list
|
||||
- md_in_html
|
||||
- pymdownx.highlight
|
||||
plugins:
|
||||
- glightbox
|
||||
- search
|
||||
- img2fig
|
||||
- with-pdf:
|
||||
cover_subtitle: Vroum Vroum
|
||||
enabled_if_env: ENABLE_PDF_EXPORT
|
||||
- annexes-integration:
|
||||
annexes: # Required (at least 1)
|
||||
- ConfigurationTool.cs: Code/ConfigurationTool.cs # An path to an annex with its title
|
||||
- DriverGapToLeaderWindow.cs: Code/DriverGapToLeaderWindow.cs # An path to an annex with its title
|
||||
- DriverPositionWindow.cs: Code/DriverPositionWindow.cs # An path to an annex with its title
|
||||
- F1TVEmulator.cs: Code/F1TVEmulator.cs # An path to an annex with its title
|
||||
- Program.cs: Code/Program.cs # An path to an annex with its title
|
||||
- Window.cs: Code/Window.cs # An path to an annex with its title
|
||||
- DriverData.cs: Code/DriverData.cs # An path to an annex with its title
|
||||
- DriverLapTimeWindow.cs: Code/DriverLapTimeWindow.cs # An path to an annex with its title
|
||||
- DriverSectorWindow.cs: Code/DriverSectorWindow.cs # An path to an annex with its title
|
||||
- Form1.cs: Code/Form1.cs # An path to an annex with its title
|
||||
- Reader.cs: Code/Reader.cs # An path to an annex with its title
|
||||
- Zone.cs: Code/Zone.cs # An path to an annex with its title
|
||||
- DriverDrsWindow.cs: Code/DriverDrsWindow.cs # An path to an annex with its title
|
||||
- DriverNameWindow.cs: Code/DriverNameWindow.cs # An path to an annex with its title
|
||||
- DriverTyresWindow.cs: Code/DriverTyresWindow.cs # An path to an annex with its title
|
||||
- OcrImage.cs: Code/OcrImage.cs # An path to an annex with its title
|
||||
- Settings.cs: Code/Settings.cs # An path to an annex with its title
|
||||
- recoverCookiesCSV.py: Code/recoverCookiesCSV.py # An path to an annex with its title
|
||||
```
|
||||
@@ -1,4 +1,6 @@
|
||||
site_name: Documentation Diplome
|
||||
site_name: Documentation Track Trends
|
||||
site_author: Rohmer Maxime
|
||||
copyright: ©CFPTI Tech2
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
@@ -18,6 +20,31 @@ theme:
|
||||
markdown_extensions:
|
||||
- attr_list
|
||||
- md_in_html
|
||||
- pymdownx.highlight
|
||||
plugins:
|
||||
- glightbox
|
||||
#- with-pdf
|
||||
- search
|
||||
- img2fig
|
||||
- with-pdf:
|
||||
cover_subtitle: Vroum Vroum
|
||||
enabled_if_env: ENABLE_PDF_EXPORT
|
||||
- annexes-integration:
|
||||
annexes: # Required (at least 1)
|
||||
- ConfigurationTool.cs: Code/ConfigurationTool.cs # An path to an annex with its title
|
||||
- DriverGapToLeaderWindow.cs: Code/DriverGapToLeaderWindow.cs # An path to an annex with its title
|
||||
- DriverPositionWindow.cs: Code/DriverPositionWindow.cs # An path to an annex with its title
|
||||
- F1TVEmulator.cs: Code/F1TVEmulator.cs # An path to an annex with its title
|
||||
- Program.cs: Code/Program.cs # An path to an annex with its title
|
||||
- Window.cs: Code/Window.cs # An path to an annex with its title
|
||||
- DriverData.cs: Code/DriverData.cs # An path to an annex with its title
|
||||
- DriverLapTimeWindow.cs: Code/DriverLapTimeWindow.cs # An path to an annex with its title
|
||||
- DriverSectorWindow.cs: Code/DriverSectorWindow.cs # An path to an annex with its title
|
||||
- Form1.cs: Code/Form1.cs # An path to an annex with its title
|
||||
- Reader.cs: Code/Reader.cs # An path to an annex with its title
|
||||
- Zone.cs: Code/Zone.cs # An path to an annex with its title
|
||||
- DriverDrsWindow.cs: Code/DriverDrsWindow.cs # An path to an annex with its title
|
||||
- DriverNameWindow.cs: Code/DriverNameWindow.cs # An path to an annex with its title
|
||||
- DriverTyresWindow.cs: Code/DriverTyresWindow.cs # An path to an annex with its title
|
||||
- OcrImage.cs: Code/OcrImage.cs # An path to an annex with its title
|
||||
- Settings.cs: Code/Settings.cs # An path to an annex with its title
|
||||
- recoverCookiesCSV.py: Code/recoverCookiesCSV.py # An path to an annex with its title
|
||||
|
||||
@@ -0,0 +1,561 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
|
||||
<meta name="author" content="Rohmer Maxime">
|
||||
|
||||
|
||||
<link rel="icon" href="/assets/images/favicon.png">
|
||||
<meta name="generator" content="mkdocs-1.4.3, mkdocs-material-8.5.0">
|
||||
|
||||
|
||||
|
||||
<title>Documentation Track Trends</title>
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/assets/stylesheets/main.2e8b5541.min.css">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/assets/stylesheets/palette.cbb835fc.min.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
|
||||
|
||||
|
||||
<script>__md_scope=new URL("/",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="" data-md-color-accent="">
|
||||
|
||||
|
||||
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
|
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav class="md-header__inner md-grid" aria-label="Header">
|
||||
<a href="/." title="Documentation Track Trends" class="md-header__button md-logo" aria-label="Documentation Track Trends" data-md-component="logo">
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
|
||||
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="" data-md-color-accent="" aria-hidden="true" type="radio" name="__palette" id="__palette_1">
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="" data-md-color-accent="" aria-hidden="true" type="radio" name="__palette" id="__palette_2">
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
</header>
|
||||
|
||||
<div class="md-container" data-md-component="container">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a href="/." title="Documentation Track Trends" class="md-nav__button md-logo" aria-label="Documentation Track Trends" data-md-component="logo">
|
||||
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
|
||||
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/." class="md-nav__link">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/CahierDesCharges/" class="md-nav__link">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/jdb/" class="md-nav__link">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--nested">
|
||||
|
||||
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" type="checkbox" id="__nav_4" >
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
|
||||
<nav class="md-nav" aria-label="Code" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/ConfigurationTool/" class="md-nav__link">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/DriverGapToLeaderWindow/" class="md-nav__link">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/DriverPositionWindow/" class="md-nav__link">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/F1TVEmulator/" class="md-nav__link">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/Program/" class="md-nav__link">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/Window/" class="md-nav__link">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/DriverData/" class="md-nav__link">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/DriverLapTimeWindow/" class="md-nav__link">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/DriverSectorWindow/" class="md-nav__link">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/Form1/" class="md-nav__link">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/Reader/" class="md-nav__link">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/Zone/" class="md-nav__link">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/DriverDrsWindow/" class="md-nav__link">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/DriverNameWindow/" class="md-nav__link">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/DriverTyresWindow/" class="md-nav__link">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/OcrImage/" class="md-nav__link">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/Settings/" class="md-nav__link">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/Code/recoverCookiesCSV/" class="md-nav__link">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
||||
|
||||
|
||||
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
|
||||
<h1>404 - Not found</h1>
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="md-footer">
|
||||
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
|
||||
<script id="__config" type="application/json">{"base": "/", "features": [], "search": "/assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
|
||||
|
||||
<script src="/assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,441 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>Cahier des charges - Documentation Track Trends</title>
|
||||
<link href="../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#cahier-des-charges">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href=".." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Cahier des charges
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href=".." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<label class="md-nav__link md-nav__link--active" for="__toc">
|
||||
Cahier des charges
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
Cahier des charges
|
||||
</a>
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
<label class="md-nav__title" for="__toc">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Table of contents
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="#contexte">
|
||||
Contexte
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="#projet">
|
||||
Projet
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="#realisation">
|
||||
Réalisation
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="#cas-dutilisation">
|
||||
Cas d'utilisation
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="#difficultes-techniques">
|
||||
Difficultés techniques
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--nested">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Code/recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
<label class="md-nav__title" for="__toc">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Table of contents
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="#contexte">
|
||||
Contexte
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="#projet">
|
||||
Projet
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="#realisation">
|
||||
Réalisation
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="#cas-dutilisation">
|
||||
Cas d'utilisation
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="#difficultes-techniques">
|
||||
Difficultés techniques
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="cahier-des-charges">Cahier des charges</h1>
|
||||
<p>Cahier des charges "Track Trends" Travail de diplôme Maxime Rohmer 2023</p>
|
||||
<h2 id="contexte">Contexte</h2>
|
||||
<hr/>
|
||||
<p>Je suis le "Live Ticker" chargé de la Formule 1 pour le 20 minutes. On peut traduire cela comme commentateur de F1, avec tout de même l'importante subtilité que je ne commente pas avec la voix, mais avec le clavier. Mes commentaires sont sous la forme de commentaires écrits live qui s'ajoutent au fur et à mesure de l'évènement.
|
||||
Par exemple : "Tour 28/54, Hamilton a fini par s'arrêter et chausser des gommes tendres 13 tours après Verstappen. L'Anglais va voir plus de 15 secondes à rattraper, mais les gommes neuves et plus tendres que son rival devraient lui permettre s'il ne se fait pas trop ralentir par le trafic". En général avec un peu plus d'infos quand même et cela tous les 3-4 tours </p>
|
||||
<p>Voici quelques exemples de précédents commentaires (Conseil : il y a un bouton pour montrer le feed dans l'ordre chronologique) :</p>
|
||||
<ul>
|
||||
<li><a href="https://www.20min.ch/fr/story/les-leaders-du-championnat-en-fond-de-grille-937035758708">"Commentaire Grand Prix de Belgique 2022"</a></li>
|
||||
<li><a href="https://www.20min.ch/fr/story/singapour-sous-la-pluie-depart-repousse-432150037887">"Commentaire du Grand Prix de Singapour 2022"</a></li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="../Images/Screens/ExampleLiveTicker.png"><img alt='"Exemple commentaires"' src="../Images/Screens/ExampleLiveTicker.png"/></a></p>
|
||||
<p>Pendant un Grand Prix, je dois constamment :</p>
|
||||
<ul>
|
||||
<li>Écrire ce qu'il se passe dans le grand prix et expliquer les enjeux</li>
|
||||
<li>Chercher régulièrement des médias à inclure pour diversifier mon live (Tweets, Images etc.)</li>
|
||||
<li>Changer le titre et la description du live en fonction de l'évolution du Grand prix</li>
|
||||
<li>Et accessoirement regarder le grand prix pour y comprendre quelque chose</li>
|
||||
</ul>
|
||||
<p>Avec tout ça, il est très difficile de garder un œil sur la page DATA de la F1TV qui fournit pourtant des informations précieuses.</p>
|
||||
<p>Je me retrouve parfois par exemple à ne pas parler de dépassements dans le peloton, car ils ne sont pas retransmis à la télé alors que c'est une information importante. Autre exemple, occasionnellement le classement ne reflète pas les vraies positions des pilotes. Les arrêts aux stands font que du coup des pilotes qui devraient être 15èmes se retrouvent 8ᵉ puisqu'ils ne sont pas encore arrêtés. Cela peut de temps en temps prêter à confusion.</p>
|
||||
<h2 id="projet">Projet</h2>
|
||||
<hr/>
|
||||
<p>Un outil de style compagnon sous forme d'application C# Windows Form qui récupère en temps réel les informations de la course et affiche les informations les plus importantes. Le but est non seulement de faciliter mon job, mais aussi faire en sorte d'améliorer la plus-value de mon travail en me permettant de fournir des commentaires qui ne sont pas disponibles pour le tout venant qui regarde simplement le flux RTS.</p>
|
||||
<p>Exemples:</p>
|
||||
<ul>
|
||||
<li>Les pilotes qui sont proches (moins de 1-2 secondes qui sont donc en train de se battre).</li>
|
||||
<li>Les pilotes qui améliorent leur temps au tour et ceux qui perdent le plus de temps</li>
|
||||
<li>Le classement pondéré tenant compte des futurs arrêts au stand</li>
|
||||
</ul>
|
||||
<p>Maintenant afficher différemment les infos, c'est sympa, mais cela serait encore mieux de traiter ces data et de permettre des petites prédictions.</p>
|
||||
<p>Exemples : </p>
|
||||
<ul>
|
||||
<li>Prédire les arrêts aux stands en prenant en compte les baisses de performances des pneus</li>
|
||||
<li>Prédire le pneu que le pilote va chausser s'il rentre aux stands dans le prochain tour</li>
|
||||
<li>Prédire dans combien de tour tel pilote va rattraper tel autre pilote</li>
|
||||
<li>Prédire combien de temps le pilote va perdre dans les stands en fonctions des arrêts précédents</li>
|
||||
</ul>
|
||||
<h2 id="realisation">Réalisation</h2>
|
||||
<p>Malheureusement, la Formula 1 Management ne propose aucune API publique qui puisse nous permettre de faire ce projet "simplement".
|
||||
La raison la plus probable étant qu'Amazon avec son service AWS propose exactement ce genre de services pour le flux télévisé et il doit y avoir un contrat d'exclusivité.</p>
|
||||
<p>Il existe des API "Pirates" faites par la communauté, le problème est qu'elles ne sont pas forcément des plus pratiques à utiliser.</p>
|
||||
<p>Mais comme je possède un abonnement premium ++ à la F1TV, j'ai accès pour chaque grand prix à un flux vidéo nommé : DATA F1 CHANNEL</p>
|
||||
<p>Qui ressemble à ça :</p>
|
||||
<p><a class="glightbox" href="../Images/Screens/Formula1DataChannel.png"><img alt='"Data channel exemple"' src="../Images/Screens/Formula1DataChannel.png"/></a></p>
|
||||
<p>Donc la seule façon que je vois de récupérer ces données est de les prendre directement sur ce feed.</p>
|
||||
<p>Même si le but final de l'application est de faire pleins de choses super avec les datas, le gros du projet va surtout être la récupération des données et leur stockage.</p>
|
||||
<p>Les données viennent du flux vidéo et ainsi dans un premier temps, il va falloir récupérer d'une manière ou d'une autre des images qui viennent d'un grand prix en direct ou en rediffusion.</p>
|
||||
<p>Ensuite, dans un second temps, il faut lire les informations directement sur l'image en utilisant une librairie prévue pour (exemple Tesseract) et vérifier l'intégrité de ces dernières pour qu'on puisse ensuite les stocker.</p>
|
||||
<p>Dans un troisième temps, il faut stocker toutes ces données dans une forme qui permette d'aller facilement faire des requêtes de récupération et déjà préparer des méthodes qui permettent de récupérer des infos importantes (ex : la moyenne des cinq derniers tours, le temps moyen d'arrêt etc.) pour faciliter la dernière étape</p>
|
||||
<p>Quand tout cela est fait, on peut ensuite s'amuser un peu avec les Data.</p>
|
||||
<p>La dernière étape est donc l'affichage. L'idée est de créer une Windows Form qui contienne toutes ces informations dans un format beaucoup plus lisible et avec laquelle on pourrait interagir pour permettre de plus facilement commenter les Grands Prix. (exemple plus bas avec un croquis de ce à quoi l'application pourrait ressembler)</p>
|
||||
<p>Voici la liste des données qui pourraient être affichées (Non contractuel, simplement des idées).</p>
|
||||
<ul>
|
||||
<li>Les pilotes qui sont proches (moins de 1-2 secondes qui sont donc en train de se battre).</li>
|
||||
<li>Les pilotes qui améliorent leur temps au tour et ceux qui perdent le plus de temps</li>
|
||||
<li>Le classement pondéré tenant compte des futurs arrêts au stand</li>
|
||||
<li>La moyenne de temps que les pilotes perdent dans les stands</li>
|
||||
<li>La performance moyenne des 5 types de pneus</li>
|
||||
<li>La moyenne de temps de chaque pilote sur le pneu actuel</li>
|
||||
<li>Le nombre de points que chaque pilote gagnerait selon sa position</li>
|
||||
<li>Le classement de la course</li>
|
||||
</ul>
|
||||
<p>Voire même si c'est possible :</p>
|
||||
<ul>
|
||||
<li>Prédire les arrêts aux stands en prenant en compte les baisses de performances des pneus</li>
|
||||
<li>Prédire le pneu que le pilote va chausser s'il rentre aux stands dans le prochain tour</li>
|
||||
<li>Prédire dans combien de tour tel pilote va rattraper tel autre pilote</li>
|
||||
<li>Prédire combien de temps le pilote va perdre dans les stands en fonctions des arrêts précédents</li>
|
||||
<li>Prédire les temps au tour de chaque pilote selon l'usure des pneus</li>
|
||||
</ul>
|
||||
<p>Voici un exemple d'interface possible pour une page :</p>
|
||||
<p><a class="glightbox" href="../Images/Figma/Prototype.png"><img alt='"Proto"' src="../Images/Figma/Prototype.png"/></a></p>
|
||||
<h2 id="cas-dutilisation">Cas d'utilisation</h2>
|
||||
<hr/>
|
||||
<p>*On va considérer que tous les user ont un abonnement F1 TV PRO</p>
|
||||
<p>Un user veut récupérer les data :</p>
|
||||
<ul>
|
||||
<li>Il ouvre son navigateur et lance la page DATA de la F1 TV</li>
|
||||
<li>Il calibre la capture des data via le programme (pour la première utilisation).</li>
|
||||
<li>Il confirme que les données initiales sont bonnes (pour la première utilisation).</li>
|
||||
<li>Il regarde tranquille son Grand Prix</li>
|
||||
</ul>
|
||||
<p>Le programme récupère les data :</p>
|
||||
<ul>
|
||||
<li>Il récupère des images depuis la F1TV</li>
|
||||
<li>Il utilise Tesseract (ou autre) pour en récupérer les infos.</li>
|
||||
<li>Il met ces infos dans un Objet Pilote, dans un Objet course avec un attribut tour pour hiérarchiser les data</li>
|
||||
</ul>
|
||||
<p>Pour ce qui est de l'affichage, l'idée est de faire une application C# comme on l'a appris à l'école, mais avec assez de style pour qu'elle puisse être agréable à utiliser.</p>
|
||||
<p>Quand le programme affiche les data :</p>
|
||||
<ul>
|
||||
<li>Il prend les données venant directement de la F1TV.</li>
|
||||
<li>Il affiche différemment les données pour permettre une meilleure lisibilité</li>
|
||||
<li>Il interprète avec des règles plutôt simples certaines data pour faire des miniprédictions ou aider à la lecture</li>
|
||||
<li>Il récupère des infos d'autres courses pour les comparer et proposer des prédictions plus intéressantes</li>
|
||||
</ul>
|
||||
<h2 id="difficultes-techniques">Difficultés techniques</h2>
|
||||
<hr/>
|
||||
<ul>
|
||||
<li>Récupérer un flux vidéo plutôt propre malgré les contres mesures de la F1 TV pour en empêcher la lecture par un logiciel</li>
|
||||
<li>Si on doit passer par une capture d'écran, trouver un moyen de stocker les données de manière à prévoir que parfois un tour pourrait avoir plus de données qu'un autre, que le user peut mettre pause, ou même qu’il revienne en arrière.</li>
|
||||
<li>Développer des algorithmes pour récupérer les données comme les différents pneus utilisés ou l'activation du DRS ainsi que développer des moyens de nettoyer les résultats de l'OCR (Par exemple utiliser différents champs redondants pour comparer les résultats)</li>
|
||||
<li>Stocker les données sur une base pour les traiter plus tard tout en prévoyant un moyen de voir les stats live</li>
|
||||
<li>Développer des algorithmes de prédiction qui prennent en compte d'anciennes courses pour tenter de prédire des choses comme les arrêts aux stands par exemple.</li>
|
||||
</ul>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: Rapport Track Trends V1.0" class="md-footer__link md-footer__link--prev" href=".." rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
Rapport Track Trends V1.0
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: Journal de bord" class="md-footer__link md-footer__link--next" href="../jdb/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
Journal de bord
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,463 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>ConfigurationTool.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#configurationtoolcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
ConfigurationTool.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="configurationtoolcs">ConfigurationTool.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : ConfigurationTool.cs
|
||||
/// Brief : Class that contains all the methods needed to create a config file for the OCR
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Tesseract;
|
||||
using System.IO;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class ConfigurationTool
|
||||
{
|
||||
public Zone MainZone;
|
||||
public const int NUMBER_OF_DRIVERS = 20;
|
||||
public const int NUMBER_OF_ZONES = 9;
|
||||
public const string CONFIGS_FOLDER_NAME = "./Presets/";
|
||||
|
||||
public ConfigurationTool(Bitmap fullImage, Rectangle mainZoneDimensions)
|
||||
{
|
||||
MainZone = new Zone(fullImage, mainZoneDimensions,"Main");
|
||||
AutoCalibrate();
|
||||
}
|
||||
public void ResetMainZone()
|
||||
{
|
||||
MainZone.ResetZones();
|
||||
}
|
||||
public void ResetWindows()
|
||||
{
|
||||
MainZone.ResetWindows();
|
||||
}
|
||||
public void SaveToJson(List<string> drivers, string configName)
|
||||
{
|
||||
string JSON = "";
|
||||
|
||||
JSON += "{" + Environment.NewLine;
|
||||
JSON += MainZone.ToJSON() + "," + Environment.NewLine;
|
||||
JSON += "\"Drivers\":[" + Environment.NewLine;
|
||||
|
||||
for (int i = 0; i < drivers.Count; i++)
|
||||
{
|
||||
JSON += "\"" + drivers[i] + "\"";
|
||||
if (i < drivers.Count - 1)
|
||||
JSON += ",";
|
||||
JSON += Environment.NewLine;
|
||||
}
|
||||
|
||||
JSON += "]" + Environment.NewLine;
|
||||
|
||||
JSON += "}";
|
||||
|
||||
if (!Directory.Exists(CONFIGS_FOLDER_NAME))
|
||||
Directory.CreateDirectory(CONFIGS_FOLDER_NAME);
|
||||
|
||||
string path = CONFIGS_FOLDER_NAME + configName;
|
||||
|
||||
if (File.Exists(path + ".json"))
|
||||
{
|
||||
//We need to create a new name
|
||||
int count = 2;
|
||||
while (File.Exists(path + "_" + count + ".json"))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
path += "_" + count + ".json";
|
||||
}
|
||||
else
|
||||
{
|
||||
path += ".json";
|
||||
}
|
||||
|
||||
File.WriteAllText(path, JSON);
|
||||
}
|
||||
public void AddWindows(List<Rectangle> rectangles)
|
||||
{
|
||||
foreach (Zone driverZone in MainZone.Zones)
|
||||
{
|
||||
Bitmap zoneImage = driverZone.ZoneImage;
|
||||
|
||||
for (int i = 1; i <= rectangles.Count; i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
//First zone should be the driver's Position
|
||||
driverZone.AddWindow(new DriverPositionWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 2:
|
||||
//First zone should be the Gap to leader
|
||||
driverZone.AddWindow(new DriverGapToLeaderWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 3:
|
||||
//First zone should be the driver's Lap Time
|
||||
driverZone.AddWindow(new DriverLapTimeWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 4:
|
||||
//First zone should be the driver's DRS status
|
||||
driverZone.AddWindow(new DriverDrsWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 5:
|
||||
//First zone should be the driver's Tyre's informations
|
||||
driverZone.AddWindow(new DriverTyresWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 6:
|
||||
//First zone should be the driver's Name
|
||||
driverZone.AddWindow(new DriverNameWindow(driverZone.ZoneImage, rectangles[i - 1], false));
|
||||
break;
|
||||
case 7:
|
||||
//First zone should be the driver's First Sector
|
||||
driverZone.AddWindow(new DriverSectorWindow(driverZone.ZoneImage, rectangles[i - 1], 1, false));
|
||||
break;
|
||||
case 8:
|
||||
//First zone should be the driver's Second Sector
|
||||
driverZone.AddWindow(new DriverSectorWindow(driverZone.ZoneImage, rectangles[i - 1], 2, false));
|
||||
break;
|
||||
case 9:
|
||||
//First zone should be the driver's Position Sector
|
||||
driverZone.AddWindow(new DriverSectorWindow(driverZone.ZoneImage, rectangles[i - 1], 3, false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public void AutoCalibrate()
|
||||
{
|
||||
List<Rectangle> detectedText = new List<Rectangle>();
|
||||
List<Zone> zones = new List<Zone>();
|
||||
|
||||
TesseractEngine engine = new TesseractEngine(Window.TESS_DATA_FOLDER.FullName, "eng", EngineMode.Default);
|
||||
Image image = MainZone.ZoneImage;
|
||||
var tessImage = Pix.LoadFromMemory(Window.ImageToByte(image));
|
||||
|
||||
Page page = engine.Process(tessImage);
|
||||
using (var iter = page.GetIterator())
|
||||
{
|
||||
iter.Begin();
|
||||
do
|
||||
{
|
||||
Rect boundingBox;
|
||||
if (iter.TryGetBoundingBox(PageIteratorLevel.Word, out boundingBox))
|
||||
{
|
||||
//var text = iter.GetText(PageIteratorLevel.Word).ToUpper();
|
||||
//We remove all the rectangles that are definitely too big
|
||||
if (boundingBox.Height < image.Height / NUMBER_OF_DRIVERS)
|
||||
{
|
||||
//Now we add a filter to only get the boxes in the right because they are much more reliable in size
|
||||
if (boundingBox.X1 > image.Width / 2)
|
||||
{
|
||||
//Now we check if an other square box has been found roughly in the same y axis
|
||||
bool match = false;
|
||||
//The tolerance is roughly half the size that a window will be
|
||||
int tolerance = (image.Height / NUMBER_OF_DRIVERS) / 2;
|
||||
|
||||
foreach (Rectangle rect in detectedText)
|
||||
{
|
||||
if (rect.Y > boundingBox.Y1 - tolerance && rect.Y < boundingBox.Y1 + tolerance)
|
||||
{
|
||||
//There already is a rectangle in this line
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
//if nothing matched we can add it
|
||||
if (!match)
|
||||
detectedText.Add(new Rectangle(boundingBox.X1, boundingBox.Y1, boundingBox.Width, boundingBox.Height));
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (iter.Next(PageIteratorLevel.Word));
|
||||
}
|
||||
//DEBUG
|
||||
int i = 1;
|
||||
foreach (Rectangle Rectangle in detectedText)
|
||||
{
|
||||
Rectangle windowRectangle;
|
||||
Size windowSize = new Size(image.Width, image.Height / NUMBER_OF_DRIVERS);
|
||||
Point windowLocation = new Point(0, (Rectangle.Y + Rectangle.Height / 2) - windowSize.Height / 2);
|
||||
windowRectangle = new Rectangle(windowLocation, windowSize);
|
||||
//We add the driver zones
|
||||
Zone driverZone = new Zone(MainZone.ZoneImage, windowRectangle, "DriverZone");
|
||||
MainZone.AddZone(driverZone);
|
||||
|
||||
driverZone.ZoneImage.Save("Driver" + i+".png");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: Journal de bord" class="md-footer__link md-footer__link--prev" href="../../jdb/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
Journal de bord
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: DriverGapToLeaderWindow.cs" class="md-footer__link md-footer__link--next" href="../DriverGapToLeaderWindow/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
DriverGapToLeaderWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,372 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>DriverData.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#driverdatacs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
DriverData.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="driverdatacs">DriverData.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverData.cs
|
||||
/// Brief : Class used to store Driver informations
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class DriverData
|
||||
{
|
||||
public bool DRS; //True = Drs is opened
|
||||
public int GapToLeader; //In ms
|
||||
public int LapTime; //In ms
|
||||
public string Name; //Ex: LECLERC
|
||||
public int Position; //Ex: 1
|
||||
public int Sector1; //in ms
|
||||
public int Sector2; //in ms
|
||||
public int Sector3; //in ms
|
||||
public Tyre CurrentTyre;//Ex Soft 11 laps
|
||||
|
||||
public DriverData(bool dRS, int gapToLeader, int lapTime, string name, int position, int sector1, int sector2, int sector3, Tyre tyre)
|
||||
{
|
||||
DRS = dRS;
|
||||
GapToLeader = gapToLeader;
|
||||
LapTime = lapTime;
|
||||
Name = name;
|
||||
Position = position;
|
||||
Sector1 = sector1;
|
||||
Sector2 = sector2;
|
||||
Sector3 = sector3;
|
||||
CurrentTyre = tyre;
|
||||
}
|
||||
public DriverData()
|
||||
{
|
||||
DRS = false;
|
||||
GapToLeader = -1;
|
||||
LapTime = -1;
|
||||
Name = "Unknown";
|
||||
Position = -1;
|
||||
Sector1 = -1;
|
||||
Sector2 = -1;
|
||||
Sector3 = -1;
|
||||
CurrentTyre = new Tyre(Tyre.Type.Undefined, -1);
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that displays all the data found in a string
|
||||
/// </summary>
|
||||
/// <returns>string containing all the driver datas</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
string result = "";
|
||||
|
||||
//Position
|
||||
result += "Position : " + Position + Environment.NewLine;
|
||||
//Gap
|
||||
result += "GapToLeader : " + Reader.ConvertMsToTime(GapToLeader) + Environment.NewLine;
|
||||
//LapTime
|
||||
result += "LapTime : " + Reader.ConvertMsToTime(LapTime) + Environment.NewLine;
|
||||
//DRS
|
||||
result += "DRS : " + DRS + Environment.NewLine;
|
||||
//Tyres
|
||||
result += "Uses " + CurrentTyre.Coumpound + " tyre " + CurrentTyre.NumberOfLaps + " laps old" + Environment.NewLine;
|
||||
//Name
|
||||
result += "DriverName : " + Name + Environment.NewLine;
|
||||
//Sector 1
|
||||
result += "Sector1 : " + Reader.ConvertMsToTime(Sector1) + Environment.NewLine;
|
||||
//Sector 1
|
||||
result += "Sector2 : " + Reader.ConvertMsToTime(Sector2) + Environment.NewLine;
|
||||
//Sector 1
|
||||
result += "Sector3 : " + Reader.ConvertMsToTime(Sector3) + Environment.NewLine;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
//Structure to store tyres infos
|
||||
public struct Tyre
|
||||
{
|
||||
//If new tyres were to be added you will have to need to change this enum
|
||||
public enum Type
|
||||
{
|
||||
Soft,
|
||||
Medium,
|
||||
Hard,
|
||||
Inter,
|
||||
Wet,
|
||||
Undefined
|
||||
}
|
||||
public Type Coumpound;
|
||||
public int NumberOfLaps;
|
||||
public Tyre(Type type, int laps)
|
||||
{
|
||||
Coumpound = type;
|
||||
NumberOfLaps = laps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: Window.cs" class="md-footer__link md-footer__link--prev" href="../Window/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
Window.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: DriverLapTimeWindow.cs" class="md-footer__link md-footer__link--next" href="../DriverLapTimeWindow/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
DriverLapTimeWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,368 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>DriverDrsWindow.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#driverdrswindowcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
DriverDrsWindow.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="driverdrswindowcs">DriverDrsWindow.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverDrsWindow.cs
|
||||
/// Brief : Window containing DRS related method and infos
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Tesseract;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal class DriverDrsWindow:Window
|
||||
{
|
||||
private static int EmptyDrsGreenValue = -1;
|
||||
private static Random rnd = new Random();
|
||||
public DriverDrsWindow(Bitmap image, Rectangle bounds,bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "DRS";
|
||||
}
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
bool result = false;
|
||||
int greenValue = GetGreenPixels();
|
||||
if (EmptyDrsGreenValue == -1)
|
||||
EmptyDrsGreenValue = greenValue;
|
||||
|
||||
if (greenValue > EmptyDrsGreenValue + EmptyDrsGreenValue / 100 * 30)
|
||||
result = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
private unsafe int GetGreenPixels()
|
||||
{
|
||||
int tot = 0;
|
||||
|
||||
Bitmap bmp = WindowImage;
|
||||
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
||||
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
for (int y = 0; y < bmp.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < bmp.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
byte blue = pixel[0];
|
||||
byte green = pixel[1];
|
||||
byte red = pixel[2];
|
||||
|
||||
if (green > blue * 1.5 && green > red * 1.5)
|
||||
{
|
||||
tot++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bmp.UnlockBits(bmpData);
|
||||
|
||||
return tot;
|
||||
}
|
||||
public Rectangle GetBox()
|
||||
{
|
||||
var tessImage = Pix.LoadFromMemory(ImageToByte(WindowImage));
|
||||
Engine.SetVariable("tessedit_char_whitelist", "");
|
||||
Page page = Engine.Process(tessImage);
|
||||
|
||||
using (var iter = page.GetIterator())
|
||||
{
|
||||
iter.Begin();
|
||||
do
|
||||
{
|
||||
Rect boundingBox;
|
||||
|
||||
// Get the bounding box for the current element
|
||||
if (iter.TryGetBoundingBox(PageIteratorLevel.Word, out boundingBox))
|
||||
{
|
||||
page.Dispose();
|
||||
return new Rectangle(boundingBox.X1, boundingBox.X2, boundingBox.Width, boundingBox.Height);
|
||||
}
|
||||
} while (iter.Next(PageIteratorLevel.Word));
|
||||
|
||||
page.Dispose();
|
||||
return new Rectangle(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: Zone.cs" class="md-footer__link md-footer__link--prev" href="../Zone/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
Zone.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: DriverNameWindow.cs" class="md-footer__link md-footer__link--next" href="../DriverNameWindow/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
DriverNameWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,302 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>DriverGapToLeaderWindow.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#drivergaptoleaderwindowcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
DriverGapToLeaderWindow.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="drivergaptoleaderwindowcs">DriverGapToLeaderWindow.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverGapToLeaderWindow.cs
|
||||
/// Brief : Window containing infos about the gap to the leader of a driver
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal class DriverGapToLeaderWindow:Window
|
||||
{
|
||||
public DriverGapToLeaderWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "GapToLeader";
|
||||
}
|
||||
/// <summary>
|
||||
/// Decodes the gap to leader using Tesseract OCR
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
int result = await GetTimeFromPng(WindowImage, OcrImage.WindowType.Gap, Engine);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: ConfigurationTool.cs" class="md-footer__link md-footer__link--prev" href="../ConfigurationTool/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
ConfigurationTool.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: DriverPositionWindow.cs" class="md-footer__link md-footer__link--next" href="../DriverPositionWindow/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
DriverPositionWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,302 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>DriverLapTimeWindow.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#driverlaptimewindowcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
DriverLapTimeWindow.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="driverlaptimewindowcs">DriverLapTimeWindow.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverLapTimeWindow
|
||||
/// Brief : Window containing infos about the lap time of a driver
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal class DriverLapTimeWindow:Window
|
||||
{
|
||||
public DriverLapTimeWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "LapTime";
|
||||
}
|
||||
/// <summary>
|
||||
/// Decodes the lap time contained in the image using OCR Tesseract
|
||||
/// </summary>
|
||||
/// <returns>The laptime in int (ms)</returns>
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
int result = await GetTimeFromPng(WindowImage, OcrImage.WindowType.LapTime, Engine);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: DriverData.cs" class="md-footer__link md-footer__link--prev" href="../DriverData/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
DriverData.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: DriverSectorWindow.cs" class="md-footer__link md-footer__link--next" href="../DriverSectorWindow/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
DriverSectorWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,328 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>DriverNameWindow.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#drivernamewindowcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
DriverNameWindow.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="drivernamewindowcs">DriverNameWindow.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverNameWindow
|
||||
/// Brief : Window containing infos about the name of the driver
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class DriverNameWindow : Window
|
||||
{
|
||||
public static Random rnd = new Random();
|
||||
public DriverNameWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "Name";
|
||||
}
|
||||
/// <summary>
|
||||
/// Decodes using OCR wich driver name is in the image
|
||||
/// </summary>
|
||||
/// <param name="DriverList"></param>
|
||||
/// <returns>The driver name in string</returns>
|
||||
public override async Task<object> DecodePng(List<string> DriverList)
|
||||
{
|
||||
string result = "";
|
||||
result = await GetStringFromPng(WindowImage, Engine);
|
||||
|
||||
if (!IsADriver(DriverList, result))
|
||||
{
|
||||
//I put everything in uppercase to try to lower the chances of bad answers
|
||||
result = FindClosestMatch(DriverList.ConvertAll(d => d.ToUpper()), result.ToUpper());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Verifies that the name found in the OCR is a valid name
|
||||
/// </summary>
|
||||
/// <param name="driverList"></param>
|
||||
/// <param name="potentialDriver"></param>
|
||||
/// <returns>If ye or no the driver exists</returns>
|
||||
private static bool IsADriver(List<string> driverList, string potentialDriver)
|
||||
{
|
||||
bool result = false;
|
||||
//I cant use drivers.Contains because it has missmatched cases and all
|
||||
foreach (string name in driverList)
|
||||
{
|
||||
if (name.ToUpper() == potentialDriver.ToUpper())
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: DriverDrsWindow.cs" class="md-footer__link md-footer__link--prev" href="../DriverDrsWindow/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
DriverDrsWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: DriverTyresWindow.cs" class="md-footer__link md-footer__link--next" href="../DriverTyresWindow/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
DriverTyresWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,312 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>DriverPositionWindow.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#driverpositionwindowcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
DriverPositionWindow.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="driverpositionwindowcs">DriverPositionWindow.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverPosition.cs
|
||||
/// Brief : Window containing infos about the position of a driver.
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class DriverPositionWindow:Window
|
||||
{
|
||||
public DriverPositionWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "Position";
|
||||
}
|
||||
/// <summary>
|
||||
/// Decodes the position number using Tesseract OCR
|
||||
/// </summary>
|
||||
/// <returns>The position of the pilot in int</returns>
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
string ocrResult = await GetStringFromPng(WindowImage, Engine, "0123456789");
|
||||
|
||||
int position;
|
||||
try
|
||||
{
|
||||
position = Convert.ToInt32(ocrResult);
|
||||
}
|
||||
catch
|
||||
{
|
||||
position = -1;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: DriverGapToLeaderWindow.cs" class="md-footer__link md-footer__link--prev" href="../DriverGapToLeaderWindow/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
DriverGapToLeaderWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: F1TVEmulator.cs" class="md-footer__link md-footer__link--next" href="../F1TVEmulator/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
F1TVEmulator.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,302 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>DriverSectorWindow.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#driversectorwindowcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
DriverSectorWindow.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="driversectorwindowcs">DriverSectorWindow.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverSectorWindow.cs
|
||||
/// Brief : Window containing infos about a driver sector time. Can be the first second or third, does not matter.
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal class DriverSectorWindow:Window
|
||||
{
|
||||
public DriverSectorWindow(Bitmap image, Rectangle bounds, int sectorId, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "Sector"+sectorId;
|
||||
}
|
||||
/// <summary>
|
||||
/// Decodes the sector
|
||||
/// </summary>
|
||||
/// <returns>the sector time in int (ms)</returns>
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
int ocrResult = await GetTimeFromPng(WindowImage, OcrImage.WindowType.Sector, Engine);
|
||||
return ocrResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: DriverLapTimeWindow.cs" class="md-footer__link md-footer__link--prev" href="../DriverLapTimeWindow/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
DriverLapTimeWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: Form1.cs" class="md-footer__link md-footer__link--next" href="../Form1/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
Form1.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,411 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>DriverTyresWindow.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#drivertyreswindowcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
DriverTyresWindow.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="drivertyreswindowcs">DriverTyresWindow.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : DriverTyresWindow.cs
|
||||
/// Brief : Window containing infos about a driver's tyre
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class DriverTyresWindow:Window
|
||||
{
|
||||
private static Random rnd = new Random();
|
||||
int seed = rnd.Next(0, 10000);
|
||||
|
||||
//Those are the colors I found but you can change them if they change in the future like in 2019
|
||||
public static Color SOFT_TYRE_COLOR = Color.FromArgb(0xff, 0x00, 0x00);
|
||||
public static Color MEDIUM_TYRE_COLOR = Color.FromArgb(0xf5, 0xbf, 0x00);
|
||||
public static Color HARD_TYRE_COLOR = Color.FromArgb(0xa4, 0xa5, 0xa8);
|
||||
public static Color INTER_TYRE_COLOR = Color.FromArgb(0x00, 0xa4, 0x2e);
|
||||
public static Color WET_TYRE_COLOR = Color.FromArgb(0x27, 0x60, 0xa6);
|
||||
public static Color EMPTY_COLOR = Color.FromArgb(0x20, 0x20, 0x20);
|
||||
|
||||
public DriverTyresWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||
{
|
||||
Name = "Tyres";
|
||||
}
|
||||
/// <summary>
|
||||
/// This will decode the content of the image
|
||||
/// </summary>
|
||||
/// <returns>And object containing what was on the image</returns>
|
||||
public override async Task<object> DecodePng()
|
||||
{
|
||||
return await GetTyreInfos();
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that will decode whats on the image and return the tyre infos it could manage to recover
|
||||
/// </summary>
|
||||
/// <returns>A tyre object containing tyre infos</returns>
|
||||
private async Task<Tyre> GetTyreInfos()
|
||||
{
|
||||
Bitmap tyreZone = GetSmallBitmapFromBigOne(WindowImage, FindTyreZone());
|
||||
Tyre.Type type = Tyre.Type.Undefined;
|
||||
type = GetTyreTypeFromColor(OcrImage.GetAvgColorFromBitmap(tyreZone));
|
||||
int laps = -1;
|
||||
|
||||
string number = await GetStringFromPng(tyreZone, Engine, "0123456789", OcrImage.WindowType.Tyre);
|
||||
try
|
||||
{
|
||||
laps = Convert.ToInt32(number);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//We could not convert the number so its a letter so its 0 laps old
|
||||
laps = 0;
|
||||
}
|
||||
//tyreZone.Save(Reader.DEBUG_DUMP_FOLDER + "Tyre" + type + "Laps" + laps + '#' + rnd.Next(0, 1000) + ".png");
|
||||
return new Tyre(type, laps);
|
||||
}
|
||||
/// <summary>
|
||||
/// Finds where the important part of the image is
|
||||
/// </summary>
|
||||
/// <returns>A rectangle containing position and dimensions of the important part of the image</returns>
|
||||
private Rectangle FindTyreZone()
|
||||
{
|
||||
Bitmap bmp = WindowImage;
|
||||
int currentPosition = bmp.Width;
|
||||
int height = bmp.Height / 2;
|
||||
Color limitColor = Color.FromArgb(0x50, 0x50, 0x50);
|
||||
Color currentColor = Color.FromArgb(0, 0, 0);
|
||||
|
||||
Size newWindowSize = new Size(bmp.Height - Convert.ToInt32((float)bmp.Height / 100f * 25f), bmp.Height - Convert.ToInt32((float)bmp.Height / 100f * 35f));
|
||||
|
||||
while (currentColor.R <= limitColor.R && currentColor.G <= limitColor.G && currentColor.B <= limitColor.B && currentPosition > 0)
|
||||
{
|
||||
currentPosition--;
|
||||
currentColor = bmp.GetPixel(currentPosition, height);
|
||||
}
|
||||
|
||||
//Its here to let the new window include a little bit of the right
|
||||
int CorrectedX = currentPosition - (newWindowSize.Width) + Convert.ToInt32((float)newWindowSize.Width / 100f * 10f);
|
||||
int CorrectedY = Convert.ToInt32((float)newWindowSize.Height / 100f * 35f);
|
||||
if (CorrectedX <= 0)
|
||||
return new Rectangle(0, 0, newWindowSize.Width, newWindowSize.Height);
|
||||
|
||||
return new Rectangle(CorrectedX, CorrectedY, newWindowSize.Width, newWindowSize.Height);
|
||||
}
|
||||
//This method has been created with the help of chatGPT
|
||||
/// <summary>
|
||||
/// Methods that compares a list of colors to see wich is the closest from the input color and decide wich tyre type it is
|
||||
/// </summary>
|
||||
/// <param name="inputColor">The color that you found</param>
|
||||
/// <returns>The tyre type</returns>
|
||||
public Tyre.Type GetTyreTypeFromColor(Color inputColor)
|
||||
{
|
||||
Tyre.Type type = Tyre.Type.Undefined;
|
||||
List<Color> colors = new List<Color>();
|
||||
//dont forget that if for some reason someday F1 adds a new Tyre type you will need to add it in the constants but also here in the list
|
||||
//You will also need to add it below in the Tyre object's enum and add an if in the end of this method
|
||||
colors.Add(SOFT_TYRE_COLOR);
|
||||
colors.Add(MEDIUM_TYRE_COLOR);
|
||||
colors.Add(HARD_TYRE_COLOR);
|
||||
colors.Add(INTER_TYRE_COLOR);
|
||||
colors.Add(WET_TYRE_COLOR);
|
||||
colors.Add(EMPTY_COLOR);
|
||||
|
||||
Color closestColor = colors[0];
|
||||
int closestDistance = int.MaxValue;
|
||||
foreach (Color color in colors)
|
||||
{
|
||||
int distance = Math.Abs(color.R - inputColor.R) + Math.Abs(color.G - inputColor.G) + Math.Abs(color.B - inputColor.B);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestColor = color;
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
//We cant use a switch as the colors cant be constants ...
|
||||
if (closestColor == SOFT_TYRE_COLOR)
|
||||
type = Tyre.Type.Soft;
|
||||
if (closestColor == MEDIUM_TYRE_COLOR)
|
||||
type = Tyre.Type.Medium;
|
||||
if (closestColor == HARD_TYRE_COLOR)
|
||||
type = Tyre.Type.Hard;
|
||||
if (closestColor == INTER_TYRE_COLOR)
|
||||
type = Tyre.Type.Inter;
|
||||
if (closestColor == WET_TYRE_COLOR)
|
||||
type = Tyre.Type.Wet;
|
||||
if (closestColor == EMPTY_COLOR)
|
||||
return Tyre.Type.Undefined;
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: DriverNameWindow.cs" class="md-footer__link md-footer__link--prev" href="../DriverNameWindow/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
DriverNameWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: OcrImage.cs" class="md-footer__link md-footer__link--next" href="../OcrImage/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
OcrImage.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,558 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>F1TVEmulator.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#f1tvemulatorcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
F1TVEmulator.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="f1tvemulatorcs">F1TVEmulator.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : F1TVEmulator.cs
|
||||
/// Brief : Class that contains methods to emulate a browser and navigate the F1TV website
|
||||
/// Version : 0.1
|
||||
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Firefox;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
using OpenQA.Selenium.Support.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal class F1TVEmulator
|
||||
{
|
||||
public const string COOKIE_HOST = ".formula1.com";
|
||||
public const string PYTHON_COOKIE_RETRIEVAL_FILENAME = "recoverCookiesCSV.py";
|
||||
public const string GECKODRIVER_FILENAME = @"geckodriver-v0.27.0-win64\geckodriver.exe";
|
||||
//BE CAREFULL IF YOU CHANGE IT HERE YOU NEED TO CHANGE IT IN THE PYTHON SCRIPT TOO
|
||||
public const string COOKIES_CSV_FILENAME = "cookies.csv";
|
||||
|
||||
private FirefoxDriver Driver;
|
||||
|
||||
private bool _ready;
|
||||
private string _grandPrixUrl;
|
||||
public string GrandPrixUrl { get => _grandPrixUrl; private set => _grandPrixUrl = value; }
|
||||
public bool Ready { get => _ready; set => _ready = value; }
|
||||
public F1TVEmulator(string grandPrixUrl)
|
||||
{
|
||||
GrandPrixUrl = grandPrixUrl;
|
||||
Ready = false;
|
||||
}
|
||||
private void StartCookieRecovering()
|
||||
{
|
||||
string scriptPath = PYTHON_COOKIE_RETRIEVAL_FILENAME;
|
||||
Process process = new Process();
|
||||
process.StartInfo.FileName = "python.exe";
|
||||
process.StartInfo.Arguments = scriptPath;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.Start();
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
}
|
||||
public string GetCookie(string host, string name)
|
||||
{
|
||||
StartCookieRecovering();
|
||||
string value = "";
|
||||
List<Cookie> cookies = new List<Cookie>();
|
||||
using (var reader = new StreamReader(COOKIES_CSV_FILENAME))
|
||||
{
|
||||
// Read the header row and validate column order
|
||||
string header = reader.ReadLine();
|
||||
string[] expectedColumns = { "host_key", "name", "value", "path", "expires_utc", "is_secure", "is_httponly" };
|
||||
string[] actualColumns = header.Split(',');
|
||||
for (int i = 0; i < expectedColumns.Length; i++)
|
||||
{
|
||||
if (expectedColumns[i] != actualColumns[i])
|
||||
{
|
||||
throw new InvalidOperationException($"Expected column '{expectedColumns[i]}' at index {i} but found '{actualColumns[i]}'");
|
||||
}
|
||||
}
|
||||
|
||||
// Read each data row and parse values into a Cookie object
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
string line = reader.ReadLine();
|
||||
string[] fields = line.Split(',');
|
||||
|
||||
string hostname = fields[0];
|
||||
string cookieName = fields[1];
|
||||
|
||||
if (hostname == host && cookieName == name)
|
||||
{
|
||||
value = fields[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
public async Task<int> Start()
|
||||
{
|
||||
Ready = false;
|
||||
|
||||
string loginCookieName = "login";
|
||||
string loginSessionCookieName = "login-session";
|
||||
string loginCookieValue = GetCookie(COOKIE_HOST, loginCookieName);
|
||||
string loginSessionValue = GetCookie(COOKIE_HOST, loginSessionCookieName);
|
||||
|
||||
int windowWidth = 1920;
|
||||
int windowHeight = 768;
|
||||
|
||||
var service = FirefoxDriverService.CreateDefaultService(GECKODRIVER_FILENAME);
|
||||
service.Host = "127.0.0.1";
|
||||
service.Port = 5555;
|
||||
|
||||
FirefoxProfile profile = new FirefoxProfile();
|
||||
FirefoxOptions options = new FirefoxOptions();
|
||||
//profile.SetPreference("full-screen-api.ignore-widgets", true);
|
||||
//profile.SetPreference("media.hardware-video-decoding.enabled", true);
|
||||
//profile.SetPreference("full-screen-api.enabled", true);
|
||||
options.Profile = profile;
|
||||
profile.SetPreference("layout.css.devPixelsPerPx", "1.0");
|
||||
|
||||
options.AcceptInsecureCertificates = true;
|
||||
options.AddArgument("--headless");
|
||||
//options.AddArgument("--start-maximized");
|
||||
//options.AddArgument("--window-size=1920x1080");
|
||||
//options.AddArgument("--width=" + windowWidth);
|
||||
//options.AddArgument("--height=" + windowHeight);
|
||||
//options.AddArgument("-window-size=1920x1080");
|
||||
//options.AddArgument("--width=1920");
|
||||
//options.AddArgument("--height=1080");
|
||||
//profile
|
||||
|
||||
try
|
||||
{
|
||||
Driver = new FirefoxDriver(service, options);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Ready = false;
|
||||
return 101;
|
||||
}
|
||||
|
||||
Actions actions = new Actions(Driver);
|
||||
var loginCookie = new Cookie(loginCookieName, loginCookieValue, COOKIE_HOST, "/", DateTime.Now.AddDays(5));
|
||||
var loginSessionCookie = new Cookie(loginSessionCookieName, loginSessionValue, COOKIE_HOST, "/", DateTime.Now.AddDays(5));
|
||||
|
||||
Driver.Navigate().GoToUrl("https://f1tv.formula1.com/");
|
||||
|
||||
Driver.Manage().Cookies.AddCookie(loginCookie);
|
||||
Driver.Manage().Cookies.AddCookie(loginSessionCookie);
|
||||
|
||||
try
|
||||
{
|
||||
Driver.Navigate().GoToUrl(GrandPrixUrl);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//The url is not a valid url
|
||||
Driver.Dispose();
|
||||
return 103;
|
||||
}
|
||||
|
||||
//Waits for the page to fully load
|
||||
Driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(30);
|
||||
|
||||
//Removes the cookie prompt
|
||||
try
|
||||
{
|
||||
IWebElement conscentButton = Driver.FindElement(By.Id("truste-consent-button"));
|
||||
conscentButton.Click();
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Could not locate the cookie button
|
||||
Screenshot("ERROR104");
|
||||
Driver.Dispose();
|
||||
return 104;
|
||||
}
|
||||
|
||||
//Again waits for the page to fully load (when you accept cookies it takes a little time for the page to load)
|
||||
//Cannot use The timeout because the feed loading is not really loading so there is not event or anything
|
||||
Thread.Sleep(5000);
|
||||
|
||||
//Switches to the Data channel
|
||||
try
|
||||
{
|
||||
IWebElement dataChannelButton = Driver.FindElement(By.ClassName("data-button"));
|
||||
dataChannelButton.Click();
|
||||
}
|
||||
catch
|
||||
{
|
||||
//If the data button does not exists its because the user is not connected
|
||||
Screenshot("ERROR102");
|
||||
Driver.Dispose();
|
||||
return 102;
|
||||
}
|
||||
|
||||
//Open settings
|
||||
// Press the space key, this should make the setting button visible
|
||||
// It does not matter if the feed is paused because when changing channel it autoplays
|
||||
actions.SendKeys(OpenQA.Selenium.Keys.Space).Perform();
|
||||
//Clicks on the settings Icon
|
||||
|
||||
int tries = 0;
|
||||
bool success = false;
|
||||
while (tries < 100 && !success)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
try
|
||||
{
|
||||
IWebElement settingsButton = Driver.FindElement(By.ClassName("bmpui-ui-settingstogglebutton"));
|
||||
settingsButton.Click();
|
||||
IWebElement selectElement = Driver.FindElement(By.ClassName("bmpui-ui-videoqualityselectbox"));
|
||||
SelectElement select = new SelectElement(selectElement);
|
||||
IWebElement selectOption = selectElement.FindElement(By.CssSelector("option[value^='1080_']"));
|
||||
selectOption.Click();
|
||||
success = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Sometimes it can crash because it could not get the options to show up in time. When it happens just retry
|
||||
success = false;
|
||||
tries++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Screenshot("ERROR105");
|
||||
Driver.Dispose();
|
||||
return 105;
|
||||
}
|
||||
|
||||
Screenshot("BEFOREFULLSCREEN");
|
||||
|
||||
//Makes the feed fullscreen
|
||||
//Driver.Manage().Window.Size = new System.Drawing.Size(windowWidth, windowHeight);
|
||||
Driver.Manage().Window.Maximize();
|
||||
WebDriverWait wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(10));
|
||||
try
|
||||
{
|
||||
IWebElement fullScreenButton = Driver.FindElement(By.ClassName("bmpui-ui-fullscreentogglebutton"));
|
||||
fullScreenButton.Click();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Screenshot("ERROR106");
|
||||
Driver.Dispose();
|
||||
return 106;
|
||||
}
|
||||
|
||||
Screenshot("AFTERFULLSCREEN");
|
||||
|
||||
//STARTUP FINISHED READY TO SCREENSHOT
|
||||
Ready = true;
|
||||
return 0;
|
||||
}
|
||||
public Bitmap Screenshot(string name = "TEST")
|
||||
{
|
||||
Bitmap result = new Bitmap(4242, 6969);
|
||||
try
|
||||
{
|
||||
//Screenshot scrsht = ((ITakesScreenshot)Driver).GetScreenshot();
|
||||
//profileriver.SetPreference("layout.css.devPixelsPerPx", "1.0");
|
||||
|
||||
//Screenshot scrsht = Driver.GetFullPageScreenshot();
|
||||
Screenshot scrsht = Driver.GetScreenshot();
|
||||
|
||||
|
||||
byte[] screenshotBytes = Convert.FromBase64String(scrsht.AsBase64EncodedString);
|
||||
MemoryStream stream = new MemoryStream(screenshotBytes);
|
||||
|
||||
result = new Bitmap(stream);
|
||||
//result.Save(name + ".png");
|
||||
scrsht.SaveAsFile(name + ".png");
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Nothing for now
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public void Stop()
|
||||
{
|
||||
Ready = false;
|
||||
Driver.Dispose();
|
||||
}
|
||||
public void ResetDriver()
|
||||
{
|
||||
Ready = false;
|
||||
Driver.Dispose();
|
||||
Driver = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: DriverPositionWindow.cs" class="md-footer__link md-footer__link--prev" href="../DriverPositionWindow/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
DriverPositionWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: Program.cs" class="md-footer__link md-footer__link--next" href="../Program/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
Program.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,297 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>Form1.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#form1cs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Form1.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="form1cs">Form1.cs</h1>
|
||||
<pre><code class="language-cs">using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public partial class Form1 : Form
|
||||
{
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void btnSettings_Click(object sender, EventArgs e)
|
||||
{
|
||||
Settings settingsForm = new Settings();
|
||||
settingsForm.ShowDialog();
|
||||
MessageBox.Show(settingsForm.GrandPrixUrl + Environment.NewLine + settingsForm.GrandPrixName + Environment.NewLine + settingsForm.GrandPrixYear);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: DriverSectorWindow.cs" class="md-footer__link md-footer__link--prev" href="../DriverSectorWindow/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
DriverSectorWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: Reader.cs" class="md-footer__link md-footer__link--next" href="../Reader/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
Reader.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,809 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>OcrImage.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#ocrimagecs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
OcrImage.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="ocrimagecs">OcrImage.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : OcrImage.cs
|
||||
/// Brief : Class containing all the methods used to enhance images for OCR
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class OcrImage
|
||||
{
|
||||
//this is a hardcoded value based on the colors of the F1TV data channel background you can change it if sometime in the future the color changes
|
||||
//Any color that has any of its R,G or B channel higher than the treshold will be considered as being usefull information
|
||||
public static Color F1TV_BACKGROUND_TRESHOLD = Color.FromArgb(0x50, 0x50, 0x50);
|
||||
Bitmap InputBitmap;
|
||||
public enum WindowType
|
||||
{
|
||||
LapTime,
|
||||
Text,
|
||||
Sector,
|
||||
Gap,
|
||||
Tyre,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new Ocr image to help enhance the given bitmap for OCR
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The image you want to enhance</param>
|
||||
public OcrImage(Bitmap inputBitmap)
|
||||
{
|
||||
InputBitmap = inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Enhances the image depending on wich type of window the image comes from
|
||||
/// </summary>
|
||||
/// <param name="type">The type of the window. Depending on it different enhancing features will be applied</param>
|
||||
/// <returns>The enhanced Bitmap</returns>
|
||||
public Bitmap Enhance(WindowType type = WindowType.Text)
|
||||
{
|
||||
Bitmap outputBitmap = (Bitmap)InputBitmap.Clone();
|
||||
switch (type)
|
||||
{
|
||||
case WindowType.LapTime:
|
||||
outputBitmap = Tresholding(outputBitmap, 185);
|
||||
outputBitmap = Resize(outputBitmap, 2);
|
||||
outputBitmap = Dilatation(outputBitmap, 1);
|
||||
outputBitmap = Erode(outputBitmap, 1);
|
||||
break;
|
||||
case WindowType.Text:
|
||||
outputBitmap = InvertColors(outputBitmap);
|
||||
outputBitmap = Tresholding(outputBitmap, 165);
|
||||
outputBitmap = Resize(outputBitmap, 2);
|
||||
outputBitmap = Dilatation(outputBitmap, 1);
|
||||
break;
|
||||
case WindowType.Tyre:
|
||||
outputBitmap = RemoveUseless(outputBitmap);
|
||||
outputBitmap = Resize(outputBitmap, 4);
|
||||
outputBitmap = Dilatation(outputBitmap, 1);
|
||||
break;
|
||||
default:
|
||||
outputBitmap = Tresholding(outputBitmap, 165);
|
||||
outputBitmap = Resize(outputBitmap, 4);
|
||||
outputBitmap = Erode(outputBitmap, 1);
|
||||
break;
|
||||
}
|
||||
return outputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that convert a colored RGB bitmap into a GrayScale image
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The Bitmap you want to convert</param>
|
||||
/// <returns>The bitmap in grayscale</returns>
|
||||
public static Bitmap Grayscale(Bitmap inputBitmap)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
byte blue = pixel[0];
|
||||
byte green = pixel[1];
|
||||
byte red = pixel[2];
|
||||
|
||||
//Those a specific values to correct the weights so its more pleasing to the human eye
|
||||
int gray = (int)(red * 0.3 + green * 0.59 + blue * 0.11);
|
||||
|
||||
pixel[0] = pixel[1] = pixel[2] = (byte)gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
|
||||
return inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that binaries the input image up to a certain treshold given
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">the bitmap you want to convert to binary colors</param>
|
||||
/// <param name="threshold">The floor at wich the color is considered as white or black</param>
|
||||
/// <returns>The binarised bitmap</returns>
|
||||
public static Bitmap Tresholding(Bitmap inputBitmap, int threshold)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
int bmpHeight = inputBitmap.Height;
|
||||
int bmpWidth = inputBitmap.Width;
|
||||
Parallel.For(0, bmpHeight, y =>
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < bmpWidth; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
byte blue = pixel[0];
|
||||
byte green = pixel[1];
|
||||
byte red = pixel[2];
|
||||
//Those a specific values to correct the weights so its more pleasing to the human eye
|
||||
int gray = (int)(red * 0.3 + green * 0.59 + blue * 0.11);
|
||||
int value = gray < threshold ? 0 : 255;
|
||||
|
||||
pixel[0] = pixel[1] = pixel[2] = (byte)value;
|
||||
}
|
||||
});
|
||||
}
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
|
||||
return inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that removes the pixels that are flagged as background
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to remove the background from</param>
|
||||
/// <returns>The Bitmap without the background</returns>
|
||||
public static Bitmap RemoveBG(Bitmap inputBitmap)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
int B = pixel[0];
|
||||
int G = pixel[1];
|
||||
int R = pixel[2];
|
||||
|
||||
if (R <= F1TV_BACKGROUND_TRESHOLD.R && G <= F1TV_BACKGROUND_TRESHOLD.G && B <= F1TV_BACKGROUND_TRESHOLD.B)
|
||||
pixel[0] = pixel[1] = pixel[2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
|
||||
return inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that removes all the useless things from the image and returns hopefully only the numbers
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to remove useless things from (Expects a cropped part of the TyreWindow)</param>
|
||||
/// <returns>The bitmap with (hopefully) only the digits</returns>
|
||||
public unsafe static Bitmap RemoveUseless(Bitmap inputBitmap)
|
||||
{
|
||||
//Note you can use something else than a cropped tyre window but I would recommend checking the code first to see if it fits your intended use
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
|
||||
List<int> pixelsToRemove = new List<int>();
|
||||
|
||||
bool fromBorder = true;
|
||||
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
int B = pixel[0];
|
||||
int G = pixel[1];
|
||||
int R = pixel[2];
|
||||
|
||||
if (fromBorder && B < F1TV_BACKGROUND_TRESHOLD.B && G < F1TV_BACKGROUND_TRESHOLD.G && R < F1TV_BACKGROUND_TRESHOLD.R)
|
||||
{
|
||||
pixelsToRemove.Add(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fromBorder)
|
||||
{
|
||||
fromBorder = false;
|
||||
pixelsToRemove.Add(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
fromBorder = true;
|
||||
for (int x = inputBitmap.Width - 1; x > 0; x--)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
int B = pixel[0];
|
||||
int G = pixel[1];
|
||||
int R = pixel[2];
|
||||
|
||||
if (fromBorder && B < F1TV_BACKGROUND_TRESHOLD.B && G < F1TV_BACKGROUND_TRESHOLD.G && R < F1TV_BACKGROUND_TRESHOLD.R)
|
||||
{
|
||||
pixelsToRemove.Add(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fromBorder)
|
||||
{
|
||||
fromBorder = false;
|
||||
pixelsToRemove.Add(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (int pxPos in pixelsToRemove)
|
||||
{
|
||||
byte* pixel = currentLine + (pxPos * bytesPerPixel);
|
||||
|
||||
pixel[0] = 0xFF;
|
||||
pixel[1] = 0xFF;
|
||||
pixel[2] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
//Removing the color parts
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
int B = pixel[0];
|
||||
int G = pixel[1];
|
||||
int R = pixel[2];
|
||||
|
||||
if (R >= F1TV_BACKGROUND_TRESHOLD.R + 15 || G >= F1TV_BACKGROUND_TRESHOLD.G + 15 || B >= F1TV_BACKGROUND_TRESHOLD.B + 15)
|
||||
{
|
||||
pixel[0] = 0xFF;
|
||||
pixel[1] = 0xFF;
|
||||
pixel[2] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
return inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Recovers the average colors from the Image. NOTE : It wont take in account colors that are lower than the background
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to get the average color from</param>
|
||||
/// <returns>The average color of the bitmap</returns>
|
||||
public static Color GetAvgColorFromBitmap(Bitmap inputBitmap)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
int totR = 0;
|
||||
int totG = 0;
|
||||
int totB = 0;
|
||||
|
||||
int totPixels = 1;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
int bmpHeight = inputBitmap.Height;
|
||||
int bmpWidth = inputBitmap.Width;
|
||||
Parallel.For(0, bmpHeight, y =>
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < bmpWidth; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
int B = pixel[0];
|
||||
int G = pixel[1];
|
||||
int R = pixel[2];
|
||||
|
||||
if (R >= F1TV_BACKGROUND_TRESHOLD.R || G >= F1TV_BACKGROUND_TRESHOLD.G || B >= F1TV_BACKGROUND_TRESHOLD.B)
|
||||
{
|
||||
totPixels++;
|
||||
totB += pixel[0];
|
||||
totG += pixel[1];
|
||||
totR += pixel[2];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
|
||||
return Color.FromArgb(255, Convert.ToInt32((float)totR / (float)totPixels), Convert.ToInt32((float)totG / (float)totPixels), Convert.ToInt32((float)totB / (float)totPixels));
|
||||
}
|
||||
/// <summary>
|
||||
/// This method simply inverts all the colors in a Bitmap
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">the bitmap you want to invert the colors from</param>
|
||||
/// <returns>The bitmap with inverted colors</returns>
|
||||
public static Bitmap InvertColors(Bitmap inputBitmap)
|
||||
{
|
||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||
|
||||
pixel[0] = (byte)(255 - pixel[0]);
|
||||
pixel[1] = (byte)(255 - pixel[1]);
|
||||
pixel[2] = (byte)(255 - pixel[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
inputBitmap.UnlockBits(bmpData);
|
||||
|
||||
return inputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Methods that applies Bicubic interpolation to increase the size and resolution of an image
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to resize</param>
|
||||
/// <param name="resizeFactor">The factor of resizing you want to use. I recommend using even numbers</param>
|
||||
/// <returns>The bitmap witht the new size</returns>
|
||||
public static Bitmap Resize(Bitmap inputBitmap, int resizeFactor)
|
||||
{
|
||||
var resultBitmap = new Bitmap(inputBitmap.Width * resizeFactor, inputBitmap.Height * resizeFactor);
|
||||
|
||||
using (var graphics = Graphics.FromImage(resultBitmap))
|
||||
{
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.DrawImage(inputBitmap, new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height));
|
||||
}
|
||||
|
||||
return resultBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// method that Highlights the countours of a Bitmap
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to highlight the countours of</param>
|
||||
/// <returns>The bitmap with countours highlighted</returns>
|
||||
public static Bitmap HighlightContours(Bitmap inputBitmap)
|
||||
{
|
||||
Bitmap outputBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height);
|
||||
|
||||
Bitmap grayscale = Grayscale(inputBitmap);
|
||||
Bitmap thresholded = Tresholding(grayscale, 128);
|
||||
Bitmap dilated = Dilatation(thresholded, 3);
|
||||
Bitmap eroded = Erode(dilated, 3);
|
||||
|
||||
for (int y = 0; y < inputBitmap.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < inputBitmap.Width; x++)
|
||||
{
|
||||
Color pixel = inputBitmap.GetPixel(x, y);
|
||||
Color dilatedPixel = dilated.GetPixel(x, y);
|
||||
Color erodedPixel = eroded.GetPixel(x, y);
|
||||
|
||||
int gray = (int)(pixel.R * 0.3 + pixel.G * 0.59 + pixel.B * 0.11);
|
||||
int threshold = dilatedPixel.R;
|
||||
|
||||
if (gray > threshold)
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(255, 255, 255));
|
||||
}
|
||||
else if (gray <= threshold && erodedPixel.R == 0)
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(255, 0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that that erodes the morphology of a bitmap
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to erode</param>
|
||||
/// <param name="kernelSize">The amount of Erosion you want (be carefull its expensive on ressources)</param>
|
||||
/// <returns>The Bitmap with the eroded contents</returns>
|
||||
public static Bitmap Erode(Bitmap inputBitmap, int kernelSize)
|
||||
{
|
||||
Bitmap outputBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height);
|
||||
|
||||
int[,] kernel = new int[kernelSize, kernelSize];
|
||||
|
||||
for (int i = 0; i < kernelSize; i++)
|
||||
{
|
||||
for (int j = 0; j < kernelSize; j++)
|
||||
{
|
||||
kernel[i, j] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = kernelSize / 2; y < inputBitmap.Height - kernelSize / 2; y++)
|
||||
{
|
||||
for (int x = kernelSize / 2; x < inputBitmap.Width - kernelSize / 2; x++)
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
for (int i = -kernelSize / 2; i <= kernelSize / 2; i++)
|
||||
{
|
||||
for (int j = -kernelSize / 2; j <= kernelSize / 2; j++)
|
||||
{
|
||||
Color pixel = inputBitmap.GetPixel(x + i, y + j);
|
||||
int gray = (int)(pixel.R * 0.3 + pixel.G * 0.59 + pixel.B * 0.11);
|
||||
|
||||
if (gray >= 128 && kernel[i + kernelSize / 2, j + kernelSize / 2] == 1)
|
||||
{
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputBitmap;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that that use dilatation of the morphology of a bitmap
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The bitmap you want to use dilatation on</param>
|
||||
/// <param name="kernelSize">The amount of dilatation you want (be carefull its expensive on ressources)</param>
|
||||
/// <returns>The Bitmap after Dilatation</returns>
|
||||
public static Bitmap Dilatation(Bitmap inputBitmap, int kernelSize)
|
||||
{
|
||||
Bitmap outputBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height);
|
||||
|
||||
int[,] kernel = new int[kernelSize, kernelSize];
|
||||
|
||||
for (int i = 0; i < kernelSize; i++)
|
||||
{
|
||||
for (int j = 0; j < kernelSize; j++)
|
||||
{
|
||||
kernel[i, j] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = kernelSize / 2; y < inputBitmap.Height - kernelSize / 2; y++)
|
||||
{
|
||||
for (int x = kernelSize / 2; x < inputBitmap.Width - kernelSize / 2; x++)
|
||||
{
|
||||
bool flag = false;
|
||||
|
||||
for (int i = -kernelSize / 2; i <= kernelSize / 2; i++)
|
||||
{
|
||||
for (int j = -kernelSize / 2; j <= kernelSize / 2; j++)
|
||||
{
|
||||
Color pixel = inputBitmap.GetPixel(x + i, y + j);
|
||||
int gray = (int)(pixel.R * 0.3 + pixel.G * 0.59 + pixel.B * 0.11);
|
||||
|
||||
if (gray < 128 && kernel[i + kernelSize / 2, j + kernelSize / 2] == 1)
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBitmap.SetPixel(x, y, Color.FromArgb(255, 255, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputBitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: DriverTyresWindow.cs" class="md-footer__link md-footer__link--prev" href="../DriverTyresWindow/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
DriverTyresWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: Settings.cs" class="md-footer__link md-footer__link--next" href="../Settings/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
Settings.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,292 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>Program.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#programcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Program.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="programcs">Program.cs</h1>
|
||||
<pre><code class="language-cs">using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: F1TVEmulator.cs" class="md-footer__link md-footer__link--prev" href="../F1TVEmulator/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
F1TVEmulator.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: Window.cs" class="md-footer__link md-footer__link--next" href="../Window/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
Window.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,500 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>Reader.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#readercs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Reader.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="readercs">Reader.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : Reader.cs
|
||||
/// Brief : Class used to Read the config file for the OCR
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class Reader
|
||||
{
|
||||
const int NUMBER_OF_DRIVERS = 20;
|
||||
public List<string> Drivers;
|
||||
public List<Zone> MainZones;
|
||||
|
||||
public Reader(string configFile, Bitmap image,bool loadOCR = true)
|
||||
{
|
||||
MainZones = Load(image,configFile,ref Drivers,loadOCR);
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that reads the JSON config file and create all the Zones and Windows
|
||||
/// </summary>
|
||||
/// <param name="imageNumber">The image #id on wich you want to create the zones on</param>
|
||||
public static List<Zone> Load(Bitmap image,string configFilePath,ref List<string> driverListToFill,bool LoadOCR)
|
||||
{
|
||||
List<Zone> mainZones = new List<Zone>();
|
||||
Bitmap fullImage = image;
|
||||
List<string> drivers;
|
||||
Zone mainZone;
|
||||
|
||||
try
|
||||
{
|
||||
using (var streamReader = new StreamReader(configFilePath))
|
||||
{
|
||||
var jsonText = streamReader.ReadToEnd();
|
||||
var jsonDocument = JsonDocument.Parse(jsonText);
|
||||
|
||||
var driversNames = jsonDocument.RootElement.GetProperty("Drivers");
|
||||
driverListToFill = new List<string>();
|
||||
|
||||
foreach (var nameElement in driversNames.EnumerateArray())
|
||||
{
|
||||
driverListToFill.Add(nameElement.GetString());
|
||||
}
|
||||
|
||||
var mainProperty = jsonDocument.RootElement.GetProperty("Main");
|
||||
Point MainPosition = new Point(mainProperty.GetProperty("x").GetInt32(), mainProperty.GetProperty("y").GetInt32());
|
||||
Size MainSize = new Size(mainProperty.GetProperty("width").GetInt32(), mainProperty.GetProperty("height").GetInt32());
|
||||
Rectangle MainRectangle = new Rectangle(MainPosition, MainSize);
|
||||
mainZone = new Zone(image, MainRectangle,"Main");
|
||||
|
||||
var zones = mainProperty.GetProperty("Zones");
|
||||
var driverZone = zones[0].GetProperty("DriverZone");
|
||||
|
||||
Point FirstZonePosition = new Point(driverZone.GetProperty("x").GetInt32(), driverZone.GetProperty("y").GetInt32());
|
||||
Size FirstZoneSize = new Size(driverZone.GetProperty("width").GetInt32(), driverZone.GetProperty("height").GetInt32());
|
||||
|
||||
var windows = driverZone.GetProperty("Windows");
|
||||
|
||||
var driverPosition = windows[0].GetProperty("Position");
|
||||
Size driverPositionArea = new Size(driverPosition.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverPositionPosition = new Point(driverPosition.GetProperty("x").GetInt32(), driverPosition.GetProperty("y").GetInt32());
|
||||
|
||||
var driverGapToLeader = windows[0].GetProperty("GapToLeader");
|
||||
Size driverGapToLeaderArea = new Size(driverGapToLeader.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverGapToLeaderPosition = new Point(driverGapToLeader.GetProperty("x").GetInt32(), driverGapToLeader.GetProperty("y").GetInt32());
|
||||
|
||||
var driverLapTime = windows[0].GetProperty("LapTime");
|
||||
Size driverLapTimeArea = new Size(driverLapTime.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverLapTimePosition = new Point(driverLapTime.GetProperty("x").GetInt32(), driverLapTime.GetProperty("y").GetInt32());
|
||||
|
||||
|
||||
var driverDrs = windows[0].GetProperty("DRS");
|
||||
Size driverDrsArea = new Size(driverDrs.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverDrsPosition = new Point(driverDrs.GetProperty("x").GetInt32(), driverDrs.GetProperty("y").GetInt32());
|
||||
|
||||
var driverTyres = windows[0].GetProperty("Tyres");
|
||||
Size driverTyresArea = new Size(driverTyres.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverTyresPosition = new Point(driverTyres.GetProperty("x").GetInt32(), driverTyres.GetProperty("y").GetInt32());
|
||||
|
||||
var driverName = windows[0].GetProperty("Name");
|
||||
Size driverNameArea = new Size(driverName.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverNamePosition = new Point(driverName.GetProperty("x").GetInt32(), driverName.GetProperty("y").GetInt32());
|
||||
|
||||
var driverSector1 = windows[0].GetProperty("Sector1");
|
||||
Size driverSector1Area = new Size(driverSector1.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverSector1Position = new Point(driverSector1.GetProperty("x").GetInt32(), driverSector1.GetProperty("y").GetInt32());
|
||||
|
||||
var driverSector2 = windows[0].GetProperty("Sector2");
|
||||
Size driverSector2Area = new Size(driverSector2.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverSector2Position = new Point(driverSector2.GetProperty("x").GetInt32(), driverSector2.GetProperty("y").GetInt32());
|
||||
|
||||
var driverSector3 = windows[0].GetProperty("Sector3");
|
||||
Size driverSector3Area = new Size(driverSector3.GetProperty("width").GetInt32(), FirstZoneSize.Height);
|
||||
Point driverSector3Position = new Point(driverSector3.GetProperty("x").GetInt32(), driverSector3.GetProperty("y").GetInt32());
|
||||
|
||||
float offset = (((float)mainZone.ZoneImage.Height - (float)(driverListToFill.Count * FirstZoneSize.Height)) / (float)driverListToFill.Count);
|
||||
Bitmap MainZoneImage = mainZone.ZoneImage;
|
||||
List<Zone> zonesToAdd = new List<Zone>();
|
||||
List<Bitmap> zonesImages = new List<Bitmap>();
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_DRIVERS; i++)
|
||||
{
|
||||
Point tmpPos = new Point(0, FirstZonePosition.Y + i * FirstZoneSize.Height - Convert.ToInt32(i * offset));
|
||||
Zone newDriverZone = new Zone(MainZoneImage, new Rectangle(tmpPos, FirstZoneSize), "DriverZone");
|
||||
zonesToAdd.Add(newDriverZone);
|
||||
zonesImages.Add(newDriverZone.ZoneImage);
|
||||
|
||||
newDriverZone.ZoneImage.Save("Driver"+i+".png");
|
||||
}
|
||||
|
||||
//Parallel.For(0, NUMBER_OF_DRIVERS, i =>
|
||||
for (int i = 0; i < NUMBER_OF_DRIVERS; i++)
|
||||
{
|
||||
Zone newDriverZone = zonesToAdd[(int)i];
|
||||
Bitmap zoneImg = zonesImages[(int)i];
|
||||
|
||||
newDriverZone.AddWindow(new DriverPositionWindow(zoneImg, new Rectangle(driverPositionPosition, driverPositionArea),LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverGapToLeaderWindow(zoneImg, new Rectangle(driverGapToLeaderPosition, driverGapToLeaderArea), LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverLapTimeWindow(zoneImg, new Rectangle(driverLapTimePosition, driverLapTimeArea), LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverDrsWindow(zoneImg, new Rectangle(driverDrsPosition, driverDrsArea), LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverTyresWindow(zoneImg, new Rectangle(driverTyresPosition, driverTyresArea), LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverNameWindow(zoneImg, new Rectangle(driverNamePosition, driverNameArea), LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverSectorWindow(zoneImg, new Rectangle(driverSector1Position, driverSector1Area),1, LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverSectorWindow(zoneImg, new Rectangle(driverSector2Position, driverSector2Area),2, LoadOCR));
|
||||
newDriverZone.AddWindow(new DriverSectorWindow(zoneImg, new Rectangle(driverSector3Position, driverSector3Area),3, LoadOCR));
|
||||
|
||||
mainZone.AddZone(newDriverZone);
|
||||
}//);
|
||||
//MessageBox.Show("We have a main zone with " + MainZone.Zones.Count() + " Driver zones with " + MainZone.Zones[4].Windows.Count() + " windows each and we have " + Drivers.Count + " drivers");
|
||||
mainZones.Add(mainZone);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
MessageBox.Show("Error reading JSON file: " + ex.Message);
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
MessageBox.Show("Invalid JSON format: " + ex.Message);
|
||||
}
|
||||
return mainZones;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that calls all the zones and windows to get the content they can find on the image to display them
|
||||
/// </summary>
|
||||
/// <param name="idImage">The id of the image we are working with</param>
|
||||
/// <returns>a string representation of all the returns</returns>
|
||||
public async Task<string> Decode(List<Zone> mainZones,List<string> drivers)
|
||||
{
|
||||
string result = "";
|
||||
List<DriverData> mainResults = new List<DriverData>();
|
||||
|
||||
//Decode
|
||||
for (int mainZoneId = 0; mainZoneId < mainZones.Count; mainZoneId++)
|
||||
{
|
||||
switch (mainZoneId)
|
||||
{
|
||||
case 0:
|
||||
//Main Zone
|
||||
foreach (Zone z in mainZones[mainZoneId].Zones)
|
||||
{
|
||||
mainResults.Add(await z.Decode(Drivers));
|
||||
}
|
||||
break;
|
||||
//Next there could be a Title Zone and TrackInfoZone
|
||||
}
|
||||
}
|
||||
|
||||
//Display
|
||||
foreach (DriverData driver in mainResults)
|
||||
{
|
||||
result += driver.ToString();
|
||||
result += Environment.NewLine;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that can be used to convert an amount of miliseconds into a more readable human form
|
||||
/// </summary>
|
||||
/// <param name="amountOfMs">The given amount of miliseconds ton convert</param>
|
||||
/// <returns>A human readable string that represents the ms</returns>
|
||||
public static string ConvertMsToTime(int amountOfMs)
|
||||
{
|
||||
//Convert.ToInt32 would round upand I dont want that
|
||||
int minuts = (int)((float)amountOfMs / (1000f * 60f));
|
||||
int seconds = (int)((amountOfMs - (minuts * 60f * 1000f)) / 1000);
|
||||
int ms = amountOfMs - ((minuts * 60 * 1000) + (seconds * 1000));
|
||||
|
||||
return minuts + ":" + seconds.ToString("00") + ":" + ms.ToString("000");
|
||||
}
|
||||
/// <summary>
|
||||
/// Old method that can draw on an image where the windows and zones are created. mostly used for debugging
|
||||
/// </summary>
|
||||
/// <param name="idImage">the #id of the image we are working with</param>
|
||||
/// <returns>the drawed bitmap</returns>
|
||||
public Bitmap Draw(Bitmap image,List<Zone> mainZones)
|
||||
{
|
||||
|
||||
Graphics g = Graphics.FromImage(image);
|
||||
|
||||
foreach (Zone z in mainZones)
|
||||
{
|
||||
int count = 0;
|
||||
foreach (Zone zz in z.Zones)
|
||||
{
|
||||
g.DrawRectangle(Pens.Red, z.Bounds);
|
||||
foreach (Window w in zz.Windows)
|
||||
{
|
||||
g.DrawRectangle(Pens.Blue, new Rectangle(z.Bounds.X + zz.Bounds.X, z.Bounds.Y + zz.Bounds.Y, zz.Bounds.Width, zz.Bounds.Height));
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: Form1.cs" class="md-footer__link md-footer__link--prev" href="../Form1/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
Form1.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: Zone.cs" class="md-footer__link md-footer__link--next" href="../Zone/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
Zone.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,685 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>Settings.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#settingscs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Settings.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="settingscs">Settings.cs</h1>
|
||||
<pre><code class="language-cs">using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public partial class Settings : Form
|
||||
{
|
||||
private string _grandPrixUrl = "";
|
||||
private string _grandPrixName = "";
|
||||
private int _grandPrixYear = 2000;
|
||||
private List<string> _driverList = new List<string>();
|
||||
|
||||
private F1TVEmulator Emulator = null;
|
||||
private ConfigurationTool Config = null;
|
||||
|
||||
private bool CreatingZone = false;
|
||||
private Point ZoneP1;
|
||||
private Point ZoneP2;
|
||||
|
||||
private bool CreatingWindow = false;
|
||||
private Point WindowP1;
|
||||
private Point WindowP2;
|
||||
|
||||
List<Rectangle> WindowsToAdd = new List<Rectangle>();
|
||||
|
||||
public string GrandPrixUrl { get => _grandPrixUrl; private set => _grandPrixUrl = value; }
|
||||
public string GrandPrixName { get => _grandPrixName; private set => _grandPrixName = value; }
|
||||
public int GrandPrixYear { get => _grandPrixYear; private set => _grandPrixYear = value; }
|
||||
public List<string> DriverList { get => _driverList; private set => _driverList = value; }
|
||||
|
||||
public Settings()
|
||||
{
|
||||
InitializeComponent();
|
||||
Load();
|
||||
}
|
||||
private void Load()
|
||||
{
|
||||
RefreshUI();
|
||||
}
|
||||
private void RefreshUI()
|
||||
{
|
||||
|
||||
lsbDrivers.DataSource = null;
|
||||
lsbDrivers.DataSource = DriverList;
|
||||
|
||||
if (Directory.Exists(ConfigurationTool.CONFIGS_FOLDER_NAME))
|
||||
{
|
||||
lsbPresets.DataSource = null;
|
||||
lsbPresets.DataSource = Directory.GetFiles(ConfigurationTool.CONFIGS_FOLDER_NAME);
|
||||
}
|
||||
if (CreatingZone)
|
||||
{
|
||||
if (ZoneP1 == new Point(-1, -1))
|
||||
{
|
||||
lblZonePointsRemaning.Text = "2 points Remaining";
|
||||
}
|
||||
else
|
||||
{
|
||||
lblZonePointsRemaning.Text = "1 point Remaining";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lblZonePointsRemaning.Text = "";
|
||||
}
|
||||
|
||||
if (CreatingWindow)
|
||||
{
|
||||
if (WindowP1 == new Point(-1, -1))
|
||||
{
|
||||
lblWindowPointsRemaining.Text = "2 points Remaining";
|
||||
}
|
||||
else
|
||||
{
|
||||
lblWindowPointsRemaining.Text = "1 point Remaining";
|
||||
}
|
||||
lblWindowPointsRemaining.Text = ConfigurationTool.NUMBER_OF_ZONES - WindowsToAdd.Count() + " Windows remaining";
|
||||
}
|
||||
else
|
||||
{
|
||||
lblWindowPointsRemaining.Text = "";
|
||||
lblWindowsRemaining.Text = "";
|
||||
}
|
||||
if (Config != null)
|
||||
{
|
||||
pbxMain.Image = Config.MainZone.Draw();
|
||||
if(Config.MainZone.Zones.Count > 0)
|
||||
pbxDriverZone.Image = Config.MainZone.Zones[0].Draw();
|
||||
}
|
||||
}
|
||||
private void CreateNewZone(Point p1, Point p2)
|
||||
{
|
||||
Rectangle dimensions = CreateAbsoluteRectangle(p1, p2);
|
||||
Config = new ConfigurationTool((Bitmap)pbxMain.Image, dimensions);
|
||||
RefreshUI();
|
||||
}
|
||||
private void CreateWindows(List<Rectangle> dimensions)
|
||||
{
|
||||
if (Config != null)
|
||||
{
|
||||
Config.AddWindows(dimensions);
|
||||
}
|
||||
}
|
||||
private void tbxGpUrl_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
GrandPrixUrl = tbxGpUrl.Text;
|
||||
}
|
||||
|
||||
private void tbxGpName_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
GrandPrixName = tbxGpName.Text;
|
||||
}
|
||||
|
||||
private void tbxGpYear_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
int year;
|
||||
try
|
||||
{
|
||||
year = Convert.ToInt32(tbxGpYear.Text);
|
||||
}
|
||||
catch
|
||||
{
|
||||
year = 1545;
|
||||
}
|
||||
GrandPrixYear = year;
|
||||
}
|
||||
|
||||
private void btnAddDriver_Click(object sender, EventArgs e)
|
||||
{
|
||||
string newDriver = tbxDriverName.Text;
|
||||
DriverList.Add(newDriver);
|
||||
tbxDriverName.Text = "";
|
||||
RefreshUI();
|
||||
}
|
||||
|
||||
private void btnRemoveDriver_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (lsbDrivers.SelectedIndex >= 0)
|
||||
{
|
||||
DriverList.RemoveAt(lsbDrivers.SelectedIndex);
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
private void SwitchZoneCreation()
|
||||
{
|
||||
if (CreatingZone)
|
||||
{
|
||||
CreatingZone = false;
|
||||
lblZonePointsRemaning.Text = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
CreatingZone = true;
|
||||
|
||||
if (Config != null)
|
||||
Config.ResetMainZone();
|
||||
|
||||
if (CreatingWindow)
|
||||
SwitchWindowCreation();
|
||||
|
||||
if (Emulator != null && Emulator.Ready)
|
||||
{
|
||||
Config = null;
|
||||
pbxMain.Image = Emulator.Screenshot();
|
||||
}
|
||||
|
||||
ZoneP1 = new Point(-1, -1);
|
||||
ZoneP2 = new Point(-1, -1);
|
||||
|
||||
lblZonePointsRemaning.Text = "2 Points left";
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
private void SwitchWindowCreation()
|
||||
{
|
||||
if (CreatingWindow)
|
||||
{
|
||||
CreatingWindow = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreatingWindow = true;
|
||||
|
||||
if (Config != null)
|
||||
Config.ResetWindows();
|
||||
|
||||
if (CreatingZone)
|
||||
SwitchZoneCreation();
|
||||
|
||||
WindowP1 = new Point(-1, -1);
|
||||
WindowP2 = new Point(-1, -1);
|
||||
|
||||
WindowsToAdd = new List<Rectangle>();
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
private void btnCreatZone_Click(object sender, EventArgs e)
|
||||
{
|
||||
SwitchZoneCreation();
|
||||
}
|
||||
private void btnCreateWindow_Click(object sender, EventArgs e)
|
||||
{
|
||||
SwitchWindowCreation();
|
||||
}
|
||||
private void pbxMain_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (CreatingZone && pbxMain.Image != null)
|
||||
{
|
||||
//Point coordinates = pbxMain.PointToClient(new Point(MousePosition.X, MousePosition.Y));
|
||||
Point coordinates = e.Location;
|
||||
float xOffset = (float)pbxMain.Image.Width / (float)pbxMain.Width;
|
||||
float yOffset = (float)pbxMain.Image.Height / (float)pbxMain.Height;
|
||||
Point newPoint = new Point(Convert.ToInt32((float)coordinates.X * xOffset), Convert.ToInt32((float)coordinates.Y * yOffset));
|
||||
|
||||
//MessageBox.Show("Coordinates" + Environment.NewLine + "Old : " + coordinates.ToString() + Environment.NewLine + "New : " + newPoint.ToString());
|
||||
|
||||
if (ZoneP1 == new Point(-1, -1))
|
||||
{
|
||||
ZoneP1 = newPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZoneP2 = newPoint;
|
||||
CreateNewZone(ZoneP1, ZoneP2);
|
||||
SwitchZoneCreation();
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
}
|
||||
private void pbxMain_Click(object sender, EventArgs e)
|
||||
{
|
||||
//Not the right one to use visibly
|
||||
}
|
||||
private void pbxDriverZone_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (CreatingWindow && pbxDriverZone.Image != null)
|
||||
{
|
||||
Point coordinates = e.Location;
|
||||
|
||||
float xOffset = (float)pbxDriverZone.Image.Width / (float)pbxDriverZone.Width;
|
||||
float yOffset = (float)pbxDriverZone.Image.Height / (float)pbxDriverZone.Height;
|
||||
|
||||
Point newPoint = new Point(Convert.ToInt32((float)coordinates.X * xOffset), Convert.ToInt32((float)coordinates.Y * yOffset));
|
||||
|
||||
if (WindowP1 == new Point(-1, -1))
|
||||
{
|
||||
WindowP1 = newPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowP2 = newPoint;
|
||||
WindowsToAdd.Add(CreateAbsoluteRectangle(WindowP1, WindowP2));
|
||||
|
||||
if (WindowsToAdd.Count < ConfigurationTool.NUMBER_OF_ZONES)
|
||||
{
|
||||
WindowP1 = new Point(-1, -1);
|
||||
WindowP2 = new Point(-1, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowP1 = new Point(WindowP1.X, 0);
|
||||
WindowP2 = new Point(WindowP2.X, pbxDriverZone.Image.Height);
|
||||
CreateWindows(WindowsToAdd);
|
||||
SwitchWindowCreation();
|
||||
}
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
}
|
||||
private void pbxDriverZone_Click(object sender, EventArgs e)
|
||||
{
|
||||
//Not the right one to use visibly
|
||||
}
|
||||
private Rectangle CreateAbsoluteRectangle(Point p1, Point p2)
|
||||
{
|
||||
Point newP1 = new Point();
|
||||
Point newP2 = new Point();
|
||||
|
||||
if (p1.X < p2.X)
|
||||
{
|
||||
newP1.X = p1.X;
|
||||
newP2.X = p2.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
newP1.X = p2.X;
|
||||
newP2.X = p1.X;
|
||||
}
|
||||
|
||||
if (p1.Y < p2.Y)
|
||||
{
|
||||
newP1.Y = p1.Y;
|
||||
newP2.Y = p2.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
newP1.Y = p2.Y;
|
||||
newP2.Y = p1.Y;
|
||||
}
|
||||
return new Rectangle(newP1.X, newP1.Y, newP2.X - newP1.X, newP2.Y - newP1.Y);
|
||||
}
|
||||
|
||||
private async void btnRefresh_Click(object sender, EventArgs e)
|
||||
{
|
||||
btnRefresh.Enabled = false;
|
||||
if (Emulator == null || Emulator.GrandPrixUrl != tbxGpUrl.Text)
|
||||
{
|
||||
Emulator = new F1TVEmulator(tbxGpUrl.Text);
|
||||
}
|
||||
|
||||
if (!Emulator.Ready)
|
||||
{
|
||||
Task<int> start = Task.Run(() => Emulator.Start());
|
||||
int errorCode = await start;
|
||||
if (errorCode != 0)
|
||||
{
|
||||
string message;
|
||||
switch (errorCode)
|
||||
{
|
||||
case 101:
|
||||
message = "Error " + errorCode + " Could not start the driver. It could be because an other instance is runnin make sure you closed them all before trying again";
|
||||
break;
|
||||
case 102:
|
||||
message = "Error " + errorCode + " Could not navigate on the F1TV site. Make sure the correct URL has been given and that you logged from chrome. It can take a few minutes to update";
|
||||
break;
|
||||
case 103:
|
||||
message = "Error " + errorCode + " The url is not a valid url";
|
||||
break;
|
||||
case 104:
|
||||
message = "Error " + errorCode + " The url is not a valid url";
|
||||
break;
|
||||
case 105:
|
||||
message = "Error " + errorCode + " There has been an error trying to emulate button presses. Please try again";
|
||||
break;
|
||||
case 106:
|
||||
message = "Error " + errorCode + " There has been an error trying to emulate button presses. Please try again";
|
||||
break;
|
||||
default:
|
||||
message = "Could not start the emulator Error " + errorCode;
|
||||
break;
|
||||
}
|
||||
MessageBox.Show(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
pbxMain.Image = Emulator.Screenshot();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pbxMain.Image = Emulator.Screenshot();
|
||||
}
|
||||
btnRefresh.Enabled = true;
|
||||
}
|
||||
|
||||
private void Settings_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
if (Emulator != null)
|
||||
{
|
||||
Emulator.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void btnResetDriver_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (Emulator != null)
|
||||
{
|
||||
Emulator.ResetDriver();
|
||||
}
|
||||
}
|
||||
|
||||
private void btnSavePreset_Click(object sender, EventArgs e)
|
||||
{
|
||||
string presetName = tbxPresetName.Text;
|
||||
if (Config != null)
|
||||
{
|
||||
Config.SaveToJson(DriverList,presetName);
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
|
||||
private void lsbPresets_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
//Nothing
|
||||
}
|
||||
|
||||
private void btnLoadPreset_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (lsbPresets.SelectedIndex >= 0 && pbxMain.Image != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Reader reader = new Reader(lsbPresets.Items[lsbPresets.SelectedIndex].ToString(), (Bitmap)pbxMain.Image,false);
|
||||
//MainZones #0 is the big main zone containing driver zones
|
||||
Config = new ConfigurationTool((Bitmap)pbxMain.Image, reader.MainZones[0].Bounds);
|
||||
Config.MainZone = reader.MainZones[0];
|
||||
DriverList = reader.Drivers;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Could not load the settings error :" + ex);
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: OcrImage.cs" class="md-footer__link md-footer__link--prev" href="../OcrImage/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
OcrImage.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: recoverCookiesCSV.py" class="md-footer__link md-footer__link--next" href="../recoverCookiesCSV/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
recoverCookiesCSV.py
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,587 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>Window.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#windowcs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Window.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="windowcs">Window.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : Window.cs
|
||||
/// Brief : Default Window object that is mainly expected to be inherited.
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using Tesseract;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class Window
|
||||
{
|
||||
private Rectangle _bounds;
|
||||
private Bitmap _image;
|
||||
private string _name;
|
||||
protected TesseractEngine Engine;
|
||||
public Rectangle Bounds { get => _bounds; private set => _bounds = value; }
|
||||
public Bitmap Image { get => _image; set => _image = value; }
|
||||
public string Name { get => _name; protected set => _name = value; }
|
||||
//This will have to be changed if you want to make it run on your machine
|
||||
public static DirectoryInfo TESS_DATA_FOLDER = new DirectoryInfo(@"C:\Users\Moi\Pictures\SeleniumScreens\TessData");
|
||||
|
||||
public Bitmap WindowImage
|
||||
{
|
||||
get
|
||||
{
|
||||
//This little trickery lets you have the image that the window sees
|
||||
Bitmap sample = new Bitmap(Bounds.Width, Bounds.Height);
|
||||
Graphics g = Graphics.FromImage(sample);
|
||||
g.DrawImage(Image, new Rectangle(0, 0, sample.Width, sample.Height), Bounds, GraphicsUnit.Pixel);
|
||||
return sample;
|
||||
}
|
||||
}
|
||||
public Window(Bitmap image, Rectangle bounds, bool generateEngine = true)
|
||||
{
|
||||
Image = image;
|
||||
Bounds = bounds;
|
||||
if (generateEngine)
|
||||
{
|
||||
Engine = new TesseractEngine(TESS_DATA_FOLDER.FullName, "eng", EngineMode.Default);
|
||||
Engine.DefaultPageSegMode = PageSegMode.SingleLine;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that will have to be used by the childrens to let the model make them decode the images they have
|
||||
/// </summary>
|
||||
/// <returns>Returns an object because we dont know what kind of return it will be</returns>
|
||||
public virtual async Task<Object> DecodePng()
|
||||
{
|
||||
return "NaN";
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that will have to be used by the childrens to let the model make them decode the images they have
|
||||
/// </summary>
|
||||
/// <param name="driverList">This is a list of the different possible drivers in the race. It should not be too big but NEVER be too short</param>
|
||||
/// <returns>Returns an object because we dont know what kind of return it will be</returns>
|
||||
public virtual async Task<Object> DecodePng(List<string> driverList)
|
||||
{
|
||||
return "NaN";
|
||||
}
|
||||
/// <summary>
|
||||
/// This converts an image into a byte[]. It can be usefull when doing unsafe stuff. Use at your own risks
|
||||
/// </summary>
|
||||
/// <param name="inputImage">The image you want to convert</param>
|
||||
/// <returns>A byte array containing the image informations</returns>
|
||||
public static byte[] ImageToByte(Image inputImage)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
inputImage.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// This method is used to recover a time from a PNG using Tesseract OCR
|
||||
/// </summary>
|
||||
/// <param name="windowImage">The image where the text is</param>
|
||||
/// <param name="windowType">The type of window it is</param>
|
||||
/// <param name="Engine">The Tesseract Engine</param>
|
||||
/// <returns>The time in milliseconds</returns>
|
||||
public static async Task<int> GetTimeFromPng(Bitmap windowImage, OcrImage.WindowType windowType, TesseractEngine Engine)
|
||||
{
|
||||
//Kind of a big method but it has a lot of error handling and has to work with three special cases
|
||||
string rawResult = "";
|
||||
int result = 0;
|
||||
|
||||
switch (windowType)
|
||||
{
|
||||
case OcrImage.WindowType.Sector:
|
||||
//The usual sector is in this form : 33.456
|
||||
Engine.SetVariable("tessedit_char_whitelist", "0123456789.");
|
||||
break;
|
||||
case OcrImage.WindowType.LapTime:
|
||||
//The usual Lap time is in this form : 1:45:345
|
||||
Engine.SetVariable("tessedit_char_whitelist", "0123456789.:");
|
||||
break;
|
||||
case OcrImage.WindowType.Gap:
|
||||
//The usual Gap is in this form : + 34.567
|
||||
Engine.SetVariable("tessedit_char_whitelist", "0123456789.+");
|
||||
break;
|
||||
default:
|
||||
Engine.SetVariable("tessedit_char_whitelist", "");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Bitmap enhancedImage = new OcrImage(windowImage).Enhance(windowType);
|
||||
|
||||
var tessImage = Pix.LoadFromMemory(ImageToByte(enhancedImage));
|
||||
|
||||
Page page = Engine.Process(tessImage);
|
||||
Graphics g = Graphics.FromImage(enhancedImage);
|
||||
// Get the iterator for the page layout
|
||||
using (var iter = page.GetIterator())
|
||||
{
|
||||
// Loop over the elements of the page layout
|
||||
iter.Begin();
|
||||
do
|
||||
{
|
||||
// Get the text for the current element
|
||||
try
|
||||
{
|
||||
rawResult += iter.GetText(PageIteratorLevel.Word);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//nothing we just dont add it if its not a number
|
||||
}
|
||||
} while (iter.Next(PageIteratorLevel.Word));
|
||||
}
|
||||
|
||||
List<string> rawNumbers;
|
||||
|
||||
//In the gaps we can find '+' but we dont care about it its redondant a driver will never be - something
|
||||
if (windowType == OcrImage.WindowType.Gap)
|
||||
rawResult = Regex.Replace(rawResult, "[^0-9.:]", "");
|
||||
|
||||
//Splits into minuts seconds miliseconds
|
||||
rawNumbers = rawResult.Split('.', ':').ToList<string>();
|
||||
//removes any empty cells (tho this usually sign of a really bad OCR implementation tbh will have to be fixed higher in the chian)
|
||||
rawNumbers.RemoveAll(x => ((string)x) == "");
|
||||
|
||||
if (rawNumbers.Count == 3)
|
||||
{
|
||||
//mm:ss:ms
|
||||
result = (Convert.ToInt32(rawNumbers[0]) * 1000 * 60) + (Convert.ToInt32(rawNumbers[1]) * 1000) + Convert.ToInt32(rawNumbers[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rawNumbers.Count == 2)
|
||||
{
|
||||
//ss:ms
|
||||
result = (Convert.ToInt32(rawNumbers[0]) * 1000) + Convert.ToInt32(rawNumbers[1]);
|
||||
|
||||
if (result > 999999)
|
||||
{
|
||||
//We know that we have way too much seconds to make a minut
|
||||
//Its usually because the ":" have been interpreted as a number
|
||||
int minuts = (int)(rawNumbers[0][0] - '0');
|
||||
// rawNumbers[0][1] should contain the : that has been mistaken
|
||||
int seconds = Convert.ToInt32(rawNumbers[0][2].ToString() + rawNumbers[0][3].ToString());
|
||||
int ms = Convert.ToInt32(rawNumbers[1]);
|
||||
result = (Convert.ToInt32(minuts) * 1000 * 60) + (Convert.ToInt32(seconds) * 1000) + Convert.ToInt32(ms);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rawNumbers.Count == 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = Convert.ToInt32(rawNumbers[0]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//It can be because the input is empty or because its the LEADER bracket
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Auuuugh
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
page.Dispose();
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Method that recovers strings from an image using Tesseract OCR
|
||||
/// </summary>
|
||||
/// <param name="WindowImage">The image of the window that contains text</param>
|
||||
/// <param name="Engine">The Tesseract engine</param>
|
||||
/// <param name="allowedChars">The list of allowed chars</param>
|
||||
/// <param name="windowType">The type of window the text is on. Depending on the context the OCR will behave differently</param>
|
||||
/// <returns>the string it found</returns>
|
||||
public static async Task<string> GetStringFromPng(Bitmap WindowImage, TesseractEngine Engine, string allowedChars = "", OcrImage.WindowType windowType = OcrImage.WindowType.Text)
|
||||
{
|
||||
string result = "";
|
||||
|
||||
Engine.SetVariable("tessedit_char_whitelist", allowedChars);
|
||||
|
||||
Bitmap rawData = WindowImage;
|
||||
Bitmap enhancedImage = new OcrImage(rawData).Enhance(windowType);
|
||||
|
||||
Page page = Engine.Process(enhancedImage);
|
||||
using (var iter = page.GetIterator())
|
||||
{
|
||||
iter.Begin();
|
||||
do
|
||||
{
|
||||
result += iter.GetText(PageIteratorLevel.Word);
|
||||
} while (iter.Next(PageIteratorLevel.Word));
|
||||
}
|
||||
page.Dispose();
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Get a smaller image from a bigger one
|
||||
/// </summary>
|
||||
/// <param name="inputBitmap">The big bitmap you want to get a part of</param>
|
||||
/// <param name="newBitmapDimensions">The dimensions of the new bitmap</param>
|
||||
/// <returns>The little bitmap</returns>
|
||||
protected Bitmap GetSmallBitmapFromBigOne(Bitmap inputBitmap, Rectangle newBitmapDimensions)
|
||||
{
|
||||
Bitmap sample = new Bitmap(newBitmapDimensions.Width, newBitmapDimensions.Height);
|
||||
Graphics g = Graphics.FromImage(sample);
|
||||
g.DrawImage(inputBitmap, new Rectangle(0, 0, sample.Width, sample.Height), newBitmapDimensions, GraphicsUnit.Pixel);
|
||||
return sample;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the closest string from a list of options
|
||||
/// </summary>
|
||||
/// <param name="options">an array of all the possibilities</param>
|
||||
/// <param name="testString">the string you want to compare</param>
|
||||
/// <returns>The closest option</returns>
|
||||
protected static string FindClosestMatch(List<string> options, string testString)
|
||||
{
|
||||
var closestMatch = "";
|
||||
var closestDistance = int.MaxValue;
|
||||
|
||||
foreach (var item in options)
|
||||
{
|
||||
var distance = LevenshteinDistance(item, testString);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestMatch = item;
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
return closestMatch;
|
||||
}
|
||||
//This method has been generated with the help of ChatGPT
|
||||
/// <summary>
|
||||
/// Method that computes a score of distance between two strings
|
||||
/// </summary>
|
||||
/// <param name="string1">The first string (order irrelevant)</param>
|
||||
/// <param name="string2">The second string (order irrelevant)</param>
|
||||
/// <returns>The levenshtein distance</returns>
|
||||
protected static int LevenshteinDistance(string string1, string string2)
|
||||
{
|
||||
if (string.IsNullOrEmpty(string1))
|
||||
{
|
||||
return string.IsNullOrEmpty(string2) ? 0 : string2.Length;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(string2))
|
||||
{
|
||||
return string.IsNullOrEmpty(string1) ? 0 : string1.Length;
|
||||
}
|
||||
|
||||
var d = new int[string1.Length + 1, string2.Length + 1];
|
||||
for (var i = 0; i <= string1.Length; i++)
|
||||
{
|
||||
d[i, 0] = i;
|
||||
}
|
||||
|
||||
for (var j = 0; j <= string2.Length; j++)
|
||||
{
|
||||
d[0, j] = j;
|
||||
}
|
||||
|
||||
for (var i = 1; i <= string1.Length; i++)
|
||||
{
|
||||
for (var j = 1; j <= string2.Length; j++)
|
||||
{
|
||||
var cost = (string1[i - 1] == string2[j - 1]) ? 0 : 1;
|
||||
d[i, j] = Math.Min(Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost);
|
||||
}
|
||||
}
|
||||
|
||||
return d[string1.Length, string2.Length];
|
||||
}
|
||||
public virtual string ToJSON()
|
||||
{
|
||||
string result = "";
|
||||
|
||||
result += "\"" + Name + "\"" + ":{" + Environment.NewLine;
|
||||
result += "\t" + "\"x\":" + Bounds.X + "," + Environment.NewLine;
|
||||
result += "\t" + "\"y\":" + Bounds.Y + "," + Environment.NewLine;
|
||||
result += "\t" + "\"width\":" + Bounds.Width + Environment.NewLine;
|
||||
result += "}";
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: Program.cs" class="md-footer__link md-footer__link--prev" href="../Program/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
Program.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: DriverData.cs" class="md-footer__link md-footer__link--next" href="../DriverData/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
DriverData.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,507 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>Zone.cs - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#zonecs">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Zone.cs
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../recoverCookiesCSV/">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="zonecs">Zone.cs</h1>
|
||||
<pre><code class="language-cs">/// Author : Maxime Rohmer
|
||||
/// Date : 08/05/2023
|
||||
/// File : Zone.cs
|
||||
/// Brief : Class that contains all the methods and infos for a zone. This is designed to be potentially be inherited.
|
||||
/// Version : 0.1
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Test_Merge
|
||||
{
|
||||
public class Zone
|
||||
{
|
||||
private Rectangle _bounds;
|
||||
private List<Zone> _zones;
|
||||
private List<Window> _windows;
|
||||
private Bitmap _image;
|
||||
private string _name;
|
||||
|
||||
public Bitmap ZoneImage
|
||||
{
|
||||
get
|
||||
{
|
||||
//This little trickery lets you have the image that the zone sees
|
||||
Bitmap sample = new Bitmap(Bounds.Width, Bounds.Height);
|
||||
Graphics g = Graphics.FromImage(sample);
|
||||
g.DrawImage(Image, new Rectangle(0, 0, sample.Width, sample.Height), Bounds, GraphicsUnit.Pixel);
|
||||
return sample;
|
||||
}
|
||||
}
|
||||
public Bitmap Image
|
||||
{
|
||||
get { return _image; }
|
||||
set
|
||||
{
|
||||
//It automatically sets the image for the contained windows and zones
|
||||
_image = Image;
|
||||
foreach (Window w in Windows)
|
||||
{
|
||||
w.Image = ZoneImage;
|
||||
}
|
||||
foreach (Zone z in Zones)
|
||||
{
|
||||
z.Image = Image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle Bounds { get => _bounds; protected set => _bounds = value; }
|
||||
public List<Zone> Zones { get => _zones; protected set => _zones = value; }
|
||||
public List<Window> Windows { get => _windows; protected set => _windows = value; }
|
||||
public string Name { get => _name; protected set => _name = value; }
|
||||
|
||||
public Zone(Bitmap image, Rectangle bounds, string name)
|
||||
{
|
||||
Windows = new List<Window>();
|
||||
Zones = new List<Zone>();
|
||||
Name = name;
|
||||
|
||||
//You cant set the image in the CTOR because the processing is impossible at first initiation
|
||||
_image = image;
|
||||
Bounds = bounds;
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a zone to the list of zones
|
||||
/// </summary>
|
||||
/// <param name="zone">The zone you want to add</param>
|
||||
public virtual void AddZone(Zone zone)
|
||||
{
|
||||
Zones.Add(zone);
|
||||
}
|
||||
/// <summary>
|
||||
/// Add a window to the list of windows
|
||||
/// </summary>
|
||||
/// <param name="window">the window you want to add</param>
|
||||
public virtual void AddWindow(Window window)
|
||||
{
|
||||
Windows.Add(window);
|
||||
}
|
||||
/// <summary>
|
||||
/// Calls all the windows to do OCR and to give back the results so we can send them to the model
|
||||
/// </summary>
|
||||
/// <param name="driverList">A list of all the driver in the race to help with text recognition</param>
|
||||
/// <returns>A driver data object that contains all the infos about a driver</returns>
|
||||
public virtual async Task<DriverData> Decode(List<string> driverList)
|
||||
{
|
||||
int sectorCount = 0;
|
||||
DriverData result = new DriverData();
|
||||
Parallel.ForEach(Windows, async w =>
|
||||
{
|
||||
// A switch would be prettier but I dont think its supported in this C# version
|
||||
if (w is DriverNameWindow)
|
||||
result.Name = (string)await (w as DriverNameWindow).DecodePng(driverList);
|
||||
if (w is DriverDrsWindow)
|
||||
result.DRS = (bool)await (w as DriverDrsWindow).DecodePng();
|
||||
if (w is DriverGapToLeaderWindow)
|
||||
result.GapToLeader = (int)await (w as DriverGapToLeaderWindow).DecodePng();
|
||||
if (w is DriverLapTimeWindow)
|
||||
result.LapTime = (int)await (w as DriverLapTimeWindow).DecodePng();
|
||||
if (w is DriverPositionWindow)
|
||||
result.Position = (int)await (w as DriverPositionWindow).DecodePng();
|
||||
if (w is DriverSectorWindow)
|
||||
{
|
||||
sectorCount++;
|
||||
if (sectorCount == 1)
|
||||
result.Sector1 = (int)await (w as DriverSectorWindow).DecodePng();
|
||||
if (sectorCount == 2)
|
||||
result.Sector2 = (int)await (w as DriverSectorWindow).DecodePng();
|
||||
if (sectorCount == 3)
|
||||
result.Sector3 = (int)await (w as DriverSectorWindow).DecodePng();
|
||||
}
|
||||
if (w is DriverTyresWindow)
|
||||
result.CurrentTyre = (Tyre)await (w as DriverTyresWindow).DecodePng();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
public virtual Bitmap Draw()
|
||||
{
|
||||
Bitmap img;
|
||||
|
||||
//If its the main zone we want to see everything
|
||||
if (Zones.Count > 0)
|
||||
{
|
||||
img = Image;
|
||||
}
|
||||
else
|
||||
{
|
||||
img = ZoneImage;
|
||||
}
|
||||
|
||||
Graphics g = Graphics.FromImage(img);
|
||||
|
||||
//If its the main zone we need to visualize the Zone bounds displayed
|
||||
if (Zones.Count > 0)
|
||||
g.DrawRectangle(new Pen(Brushes.Violet, 5), Bounds);
|
||||
|
||||
foreach (Zone z in Zones)
|
||||
{
|
||||
Rectangle newBounds = new Rectangle(z.Bounds.X, z.Bounds.Y + Bounds.Y, z.Bounds.Width, z.Bounds.Height);
|
||||
g.DrawRectangle(Pens.Red, newBounds);
|
||||
}
|
||||
foreach (Window w in Windows)
|
||||
{
|
||||
g.DrawRectangle(Pens.Blue, w.Bounds);
|
||||
}
|
||||
return img;
|
||||
}
|
||||
public void ResetZones()
|
||||
{
|
||||
Zones.Clear();
|
||||
}
|
||||
public void ResetWindows()
|
||||
{
|
||||
foreach (Zone z in Zones)
|
||||
{
|
||||
z.ResetWindows();
|
||||
}
|
||||
Windows.Clear();
|
||||
}
|
||||
public virtual string ToJSON()
|
||||
{
|
||||
string result = "";
|
||||
result += "\"" + Name + "\":{" + Environment.NewLine;
|
||||
result += "\t" + "\"x\":" + Bounds.X + "," + Environment.NewLine;
|
||||
result += "\t" + "\"y\":" + Bounds.Y + "," + Environment.NewLine;
|
||||
result += "\t" + "\"width\":" + Bounds.Width + "," + Environment.NewLine;
|
||||
result += "\t" + "\"height\":" + Bounds.Height;
|
||||
|
||||
if (Windows.Count != 0)
|
||||
{
|
||||
result += "," + Environment.NewLine;
|
||||
|
||||
result += "\t" + "\"Windows\":[" + Environment.NewLine;
|
||||
result += "\t\t{" + Environment.NewLine;
|
||||
int Wcount = 0;
|
||||
foreach (Window w in Windows)
|
||||
{
|
||||
result += "\t\t" + w.ToJSON();
|
||||
Wcount++;
|
||||
if (Wcount != Windows.Count)
|
||||
result += ",";
|
||||
}
|
||||
result += "\t\t}" + Environment.NewLine;
|
||||
result += "\t" + "]" + Environment.NewLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += Environment.NewLine;
|
||||
}
|
||||
if (Zones.Count != 0)
|
||||
{
|
||||
result += "," + Environment.NewLine;
|
||||
|
||||
result += "\t" + "\"Zones\":[" + Environment.NewLine;
|
||||
result += "\t\t{" + Environment.NewLine;
|
||||
int Zcount = 0;
|
||||
//foreach (Zone z in Zones)
|
||||
//{
|
||||
result += "\t\t" + Zones[0].ToJSON();
|
||||
Zcount++;
|
||||
if (Zcount != Zones.Count)
|
||||
//result += ",";
|
||||
//}
|
||||
result += "\t\t}" + Environment.NewLine;
|
||||
result += "\t" + "]" + Environment.NewLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += Environment.NewLine;
|
||||
}
|
||||
|
||||
result += "}";
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Checks if the given Rectangle fits in the current zone
|
||||
/// </summary>
|
||||
/// <param name="InputRectangle">The Rectangle you want to check the fittment</param>
|
||||
/// <returns></returns>
|
||||
protected bool Fits(Rectangle inputRectangle)
|
||||
{
|
||||
if (inputRectangle.X + inputRectangle.Width > Bounds.Width || inputRectangle.Y + inputRectangle.Height > Bounds.Height || inputRectangle.X < 0 || inputRectangle.Y < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: Reader.cs" class="md-footer__link md-footer__link--prev" href="../Reader/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
Reader.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Next: DriverDrsWindow.cs" class="md-footer__link md-footer__link--next" href="../DriverDrsWindow/" rel="next">
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Next
|
||||
</span>
|
||||
DriverDrsWindow.cs
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"></path></svg>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
@@ -0,0 +1,340 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||||
<meta content="Rohmer Maxime" name="author"/>
|
||||
<link href="../../assets/images/favicon.png" rel="icon"/>
|
||||
<meta content="mkdocs-1.4.3, mkdocs-material-8.5.0" name="generator"/>
|
||||
<title>recoverCookiesCSV.py - Documentation Track Trends</title>
|
||||
<link href="../../assets/stylesheets/main.2e8b5541.min.css" rel="stylesheet"/>
|
||||
<link href="../../assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/>
|
||||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" rel="stylesheet"/>
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
<link href="../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>html.glightbox-open { overflow: initial; height: 100%; }</style><script src="../../assets/javascripts/glightbox.min.js"></script></head>
|
||||
<body data-md-color-accent="" data-md-color-primary="" data-md-color-scheme="default" dir="ltr">
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
<a class="md-skip" href="#recovercookiescsvpy">
|
||||
Skip to content
|
||||
</a>
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
</div>
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav aria-label="Header" class="md-header__inner md-grid">
|
||||
<a aria-label="Documentation Track Trends" class="md-header__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"></path></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
Documentation Track Trends
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
recoverCookiesCSV.py
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: light)" data-md-color-primary="" data-md-color-scheme="default" id="__palette_1" name="__palette" type="radio"/>
|
||||
<input aria-hidden="true" class="md-option" data-md-color-accent="" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-primary="" data-md-color-scheme="slate" id="__palette_2" name="__palette" type="radio"/>
|
||||
</form>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="md-container" data-md-component="container">
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Navigation" class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a aria-label="Documentation Track Trends" class="md-nav__button md-logo" data-md-component="logo" href="../.." title="Documentation Track Trends">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"></path></svg>
|
||||
</a>
|
||||
Documentation Track Trends
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../..">
|
||||
Rapport Track Trends V1.0
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../CahierDesCharges/">
|
||||
Cahier des charges
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../../jdb/">
|
||||
Journal de bord
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||||
<input checked="" class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" id="__nav_4" type="checkbox"/>
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
Code
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav aria-label="Code" class="md-nav" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Code
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix="">
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../ConfigurationTool/">
|
||||
ConfigurationTool.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverGapToLeaderWindow/">
|
||||
DriverGapToLeaderWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverPositionWindow/">
|
||||
DriverPositionWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../F1TVEmulator/">
|
||||
F1TVEmulator.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Program/">
|
||||
Program.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Window/">
|
||||
Window.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverData/">
|
||||
DriverData.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverLapTimeWindow/">
|
||||
DriverLapTimeWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverSectorWindow/">
|
||||
DriverSectorWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Form1/">
|
||||
Form1.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Reader/">
|
||||
Reader.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Zone/">
|
||||
Zone.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverDrsWindow/">
|
||||
DriverDrsWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverNameWindow/">
|
||||
DriverNameWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../DriverTyresWindow/">
|
||||
DriverTyresWindow.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../OcrImage/">
|
||||
OcrImage.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item">
|
||||
<a class="md-nav__link" href="../Settings/">
|
||||
Settings.cs
|
||||
</a>
|
||||
</li>
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" id="__toc" type="checkbox"/>
|
||||
<a class="md-nav__link md-nav__link--active" href="./">
|
||||
recoverCookiesCSV.py
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
<nav aria-label="Table of contents" class="md-nav md-nav--secondary">
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
<h1 id="recovercookiescsvpy">recoverCookiesCSV.py</h1>
|
||||
<pre><code class="language-py"># Rohmer Maxime
|
||||
# RecoverCookies.py
|
||||
# Little script that recovers the cookies stored in the chrome sqlite database and then decrypts them using the key stored in the chrome files
|
||||
# This script has been created to be used by an other programm or for the data to not be used directly. This is why it stores all the decoded cookies in a csv. (Btw could be smart for the end programm to delete the csv after using it)
|
||||
# Parts of this cript have been created with the help of ChatGPT
|
||||
|
||||
import os
|
||||
import json
|
||||
import base64
|
||||
import sqlite3
|
||||
import win32crypt
|
||||
from Cryptodome.Cipher import AES
|
||||
from pathlib import Path
|
||||
import csv
|
||||
|
||||
def get_master_key():
|
||||
with open(
|
||||
os.getenv("localappdata") + "\\Google\\Chrome\\User Data\\Local State", "r"
|
||||
) as f:
|
||||
local_state = f.read()
|
||||
local_state = json.loads(local_state)
|
||||
master_key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
|
||||
master_key = master_key[5:] # removing DPAPI
|
||||
master_key = win32crypt.CryptUnprotectData(master_key, None, None, None, 0)[1]
|
||||
print("MASTER KEY :")
|
||||
print(master_key)
|
||||
print(len(master_key))
|
||||
return master_key
|
||||
|
||||
def decrypt_payload(cipher, payload):
|
||||
return cipher.decrypt(payload)
|
||||
|
||||
def generate_cipher(aes_key, iv):
|
||||
return AES.new(aes_key, AES.MODE_GCM, iv)
|
||||
|
||||
def decrypt_password(buff, master_key):
|
||||
try:
|
||||
iv = buff[3:15]
|
||||
payload = buff[15:]
|
||||
cipher = generate_cipher(master_key, iv)
|
||||
decrypted_pass = decrypt_payload(cipher, payload)
|
||||
decrypted_pass = decrypted_pass[:-16].decode() # remove suffix bytes
|
||||
return decrypted_pass
|
||||
except Exception:
|
||||
# print("Probably saved password from Chrome version older than v80\n")
|
||||
# print(str(e))
|
||||
return "Chrome < 80"
|
||||
|
||||
|
||||
master_key = get_master_key()
|
||||
|
||||
cookies_path = Path(
|
||||
os.getenv("localappdata") + "\\Google\\Chrome\\User Data\\Default\\Network\\Cookies"
|
||||
)
|
||||
|
||||
if not cookies_path.exists():
|
||||
raise ValueError("Cookies file not found")
|
||||
|
||||
with sqlite3.connect(cookies_path) as connection:
|
||||
connection.row_factory = sqlite3.Row
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SELECT * FROM cookies")
|
||||
|
||||
with open('cookies.csv', 'a', newline='') as csvfile:
|
||||
fieldnames = ['host_key', 'name', 'value', 'path', 'expires_utc', 'is_secure', 'is_httponly']
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
||||
|
||||
if csvfile.tell() == 0:
|
||||
writer.writeheader()
|
||||
|
||||
for row in cursor.fetchall():
|
||||
decrypted_value = decrypt_password(row["encrypted_value"], master_key)
|
||||
writer.writerow({
|
||||
'host_key': row["host_key"],
|
||||
'name': row["name"],
|
||||
'value': decrypted_value,
|
||||
'path': row["path"],
|
||||
'expires_utc': row["expires_utc"],
|
||||
'is_secure': row["is_secure"],
|
||||
'is_httponly': row["is_httponly"]
|
||||
})
|
||||
|
||||
print("Finished CSV")
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="md-footer">
|
||||
<nav aria-label="Footer" class="md-footer__inner md-grid">
|
||||
<a aria-label="Previous: Settings.cs" class="md-footer__link md-footer__link--prev" href="../Settings/" rel="prev">
|
||||
<div class="md-footer__button md-icon">
|
||||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<div class="md-ellipsis">
|
||||
<span class="md-footer__direction">
|
||||
Previous
|
||||
</span>
|
||||
Settings.cs
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
<div class="md-copyright__highlight">
|
||||
©CFPTI Tech2
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.ecf98df9.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
|
||||
<script src="../../assets/javascripts/bundle.48f2be22.min.js"></script>
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "width": "100%", "height": "auto", "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom"});})</script></body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.8 MiB |
|
After Width: | Height: | Size: 4.0 MiB |
|
After Width: | Height: | Size: 3.5 MiB |
|
After Width: | Height: | Size: 3.3 MiB |
|
After Width: | Height: | Size: 3.2 MiB |
|
After Width: | Height: | Size: 5.1 MiB |
|
After Width: | Height: | Size: 3.9 MiB |
|
After Width: | Height: | Size: 346 KiB |
|
After Width: | Height: | Size: 562 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 199 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 176 B |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 750 B |
|
After Width: | Height: | Size: 259 KiB |
|
After Width: | Height: | Size: 750 B |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 750 B |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 744 B |
|
After Width: | Height: | Size: 305 KiB |