Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf656ff2b2 | |||
| 0efeb44acf | |||
| 69ecab841f | |||
| 071ac2fe17 | |||
| a340f42ec4 | |||
| cf25a52470 | |||
| da23c40ac2 | |||
| eb98466a98 | |||
| a92b6bce8a | |||
| 963383b1cc | |||
| 9929a77b00 | |||
| bf9ce57322 | |||
| ddfb325598 | |||
| ce237a9a3f | |||
| e854a9e702 |
@@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrackTrends", "TrackTrends\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BAFC8496-36AE-4539-94DE-0E505E7A8F93}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BAFC8496-36AE-4539-94DE-0E505E7A8F93}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrackTrendsTests", "TrackTrendsTests\TrackTrendsTests.csproj", "{9BE68783-F589-479A-8CFA-9652C3B23A37}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -17,6 +19,10 @@ Global
|
|||||||
{F6694884-3B45-4017-9C9A-A0AFFC508245}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{F6694884-3B45-4017-9C9A-A0AFFC508245}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{F6694884-3B45-4017-9C9A-A0AFFC508245}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{F6694884-3B45-4017-9C9A-A0AFFC508245}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{F6694884-3B45-4017-9C9A-A0AFFC508245}.Release|Any CPU.Build.0 = Release|Any CPU
|
{F6694884-3B45-4017-9C9A-A0AFFC508245}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9BE68783-F589-479A-8CFA-9652C3B23A37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9BE68783-F589-479A-8CFA-9652C3B23A37}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9BE68783-F589-479A-8CFA-9652C3B23A37}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9BE68783-F589-479A-8CFA-9652C3B23A37}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : DataWrapper.cs
|
/// File : DataWrapper.cs
|
||||||
/// Brief : Class that is used to interface between the main Form (vue) and the Storage (wich is a class that wraps the sqlite database, so the model) its almost MVC :D
|
/// Brief : Class that is used to interface between the main Form (vue) and the Storage (wich is a class that wraps the sqlite database, so the model) its almost MVC :D
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : DriverData.cs
|
/// File : DriverData.cs
|
||||||
/// Brief : File containing classes that behave just like structures to store data about drivers
|
/// Brief : File containing classes that behave just like structures to store data about drivers
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : DriverDrsWindow.cs
|
/// File : DriverDrsWindow.cs
|
||||||
/// Brief : Window containing DRS related method and infos
|
/// Brief : Window containing DRS related method and infos
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -15,7 +15,7 @@ using Tesseract;
|
|||||||
|
|
||||||
namespace TrackTrends
|
namespace TrackTrends
|
||||||
{
|
{
|
||||||
internal class DriverDrsWindow:Window
|
public class DriverDrsWindow:Window
|
||||||
{
|
{
|
||||||
private static int EmptyDrsGreenValue = -1;
|
private static int EmptyDrsGreenValue = -1;
|
||||||
private static Random rnd = new Random();
|
private static Random rnd = new Random();
|
||||||
@@ -30,6 +30,10 @@ namespace TrackTrends
|
|||||||
public override object DecodePng()
|
public override object DecodePng()
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
|
//DEBUG
|
||||||
|
//WindowImage.Save("./DRS/"+rnd.Next(0,99999)+".png");
|
||||||
|
|
||||||
int greenValue = GetGreenPixels();
|
int greenValue = GetGreenPixels();
|
||||||
if (EmptyDrsGreenValue == -1)
|
if (EmptyDrsGreenValue == -1)
|
||||||
EmptyDrsGreenValue = greenValue;
|
EmptyDrsGreenValue = greenValue;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace TrackTrends
|
namespace TrackTrends
|
||||||
{
|
{
|
||||||
internal class DriverGapToLeaderWindow:Window
|
public class DriverGapToLeaderWindow:Window
|
||||||
{
|
{
|
||||||
public DriverGapToLeaderWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
public DriverGapToLeaderWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : DriverLapTimeWindow
|
/// File : DriverLapTimeWindow
|
||||||
/// Brief : Window containing infos about the lap time of a driver
|
/// Brief : Window containing infos about the lap time of a driver
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -13,7 +13,7 @@ using System.Drawing;
|
|||||||
|
|
||||||
namespace TrackTrends
|
namespace TrackTrends
|
||||||
{
|
{
|
||||||
internal class DriverLapTimeWindow:Window
|
public class DriverLapTimeWindow:Window
|
||||||
{
|
{
|
||||||
public DriverLapTimeWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
public DriverLapTimeWindow(Bitmap image, Rectangle bounds, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : DriverNameWindow
|
/// File : DriverNameWindow
|
||||||
/// Brief : Window containing infos about the name of the driver
|
/// Brief : Window containing infos about the name of the driver
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : DriverPositionWindow.cs
|
/// File : DriverPositionWindow.cs
|
||||||
/// Brief : Window containing infos about the position of a driver.
|
/// Brief : Window containing infos about the position of a driver.
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : DriverSectorWindow.cs
|
/// File : DriverSectorWindow.cs
|
||||||
/// Brief : Window containing infos about a driver sector time. Can be the first second or third, does not matter.
|
/// Brief : Window containing infos about a driver sector time. Can be the first second or third, does not matter.
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -13,7 +13,7 @@ using System.Drawing;
|
|||||||
|
|
||||||
namespace TrackTrends
|
namespace TrackTrends
|
||||||
{
|
{
|
||||||
internal class DriverSectorWindow:Window
|
public class DriverSectorWindow:Window
|
||||||
{
|
{
|
||||||
public DriverSectorWindow(Bitmap image, Rectangle bounds, int sectorId, bool generateEngine = true) : base(image, bounds,generateEngine)
|
public DriverSectorWindow(Bitmap image, Rectangle bounds, int sectorId, bool generateEngine = true) : base(image, bounds,generateEngine)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : DriverTyresWindow.cs
|
/// File : DriverTyresWindow.cs
|
||||||
/// Brief : Window containing infos about a driver's tyre
|
/// Brief : Window containing infos about a driver's tyre
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -15,6 +15,7 @@ namespace TrackTrends
|
|||||||
{
|
{
|
||||||
public class DriverTyresWindow:Window
|
public class DriverTyresWindow:Window
|
||||||
{
|
{
|
||||||
|
private static Random rnd = new Random();
|
||||||
//Those are the colors I found but you can change them if they change in the future like in 2019
|
//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 SOFT_TYRE_COLOR = Color.FromArgb(0xff, 0x00, 0x00);
|
||||||
public static Color MEDIUM_TYRE_COLOR = Color.FromArgb(0xf5, 0xbf, 0x00);
|
public static Color MEDIUM_TYRE_COLOR = Color.FromArgb(0xf5, 0xbf, 0x00);
|
||||||
@@ -41,6 +42,9 @@ namespace TrackTrends
|
|||||||
/// <returns>A tyre object containing tyre infos</returns>
|
/// <returns>A tyre object containing tyre infos</returns>
|
||||||
private Tyre GetTyreInfos()
|
private Tyre GetTyreInfos()
|
||||||
{
|
{
|
||||||
|
//DEBUG
|
||||||
|
//WindowImage.Save("./Tyre/raw_"+rnd.Next(0,99999)+".png");
|
||||||
|
|
||||||
Bitmap tyreZone = GetSmallBitmapFromBigOne(WindowImage, FindTyreZone());
|
Bitmap tyreZone = GetSmallBitmapFromBigOne(WindowImage, FindTyreZone());
|
||||||
Tyre.Type type = Tyre.Type.Undefined;
|
Tyre.Type type = Tyre.Type.Undefined;
|
||||||
type = GetTyreTypeFromColor(OcrImage.GetAvgColorFromBitmap(tyreZone));
|
type = GetTyreTypeFromColor(OcrImage.GetAvgColorFromBitmap(tyreZone));
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : F1TVEmulator.cs
|
/// File : F1TVEmulator.cs
|
||||||
/// Brief : Class that contains methods to emulate a browser and navigate the F1TV website
|
/// Brief : Class that contains methods to emulate a browser and navigate the F1TV website
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using OpenQA.Selenium;
|
using OpenQA.Selenium;
|
||||||
using OpenQA.Selenium.Firefox;
|
using OpenQA.Selenium.Firefox;
|
||||||
@@ -187,6 +187,18 @@ namespace TrackTrends
|
|||||||
return 104;
|
return 104;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
IWebElement LiveButton = Driver.FindElement(By.ClassName("btn-manage-account"));
|
||||||
|
//By.ClassName("btn btn-controls btn-main btn-manage-account no-redirect")
|
||||||
|
LiveButton.Click();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Console.Write("Going for a rediff");
|
||||||
|
}
|
||||||
|
|
||||||
//Again waits for the page to fully load (when you accept cookies it takes a little time for the page to load)
|
//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
|
//Cannot use The timeout because the feed loading is not really loading so there is not event or anything
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
using System;
|
/// Author : Maxime Rohmer
|
||||||
|
/// Date : 09/06/2023
|
||||||
|
/// File : Form1.cs
|
||||||
|
/// Brief : Class that controls the main view of the app
|
||||||
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
@@ -15,7 +21,6 @@ namespace TrackTrends
|
|||||||
{
|
{
|
||||||
public partial class Main : Form
|
public partial class Main : Form
|
||||||
{
|
{
|
||||||
//private Reader Reader = null;
|
|
||||||
private F1TVEmulator Emulator = null;
|
private F1TVEmulator Emulator = null;
|
||||||
private DataWrapper Wrapper = null;
|
private DataWrapper Wrapper = null;
|
||||||
private bool cancelRequested = false;
|
private bool cancelRequested = false;
|
||||||
@@ -47,7 +52,10 @@ namespace TrackTrends
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
public async void RefreshUI()
|
/// <summary>
|
||||||
|
/// Will update everything that is not data related
|
||||||
|
/// </summary>
|
||||||
|
public void RefreshUI()
|
||||||
{
|
{
|
||||||
if (Directory.Exists(ConfigurationTool.CONFIGS_FOLDER_NAME))
|
if (Directory.Exists(ConfigurationTool.CONFIGS_FOLDER_NAME))
|
||||||
{
|
{
|
||||||
@@ -55,7 +63,12 @@ namespace TrackTrends
|
|||||||
lsbPresets.DataSource = Directory.GetFiles(ConfigurationTool.CONFIGS_FOLDER_NAME);
|
lsbPresets.DataSource = Directory.GetFiles(ConfigurationTool.CONFIGS_FOLDER_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async void btnSettings_Click(object sender, EventArgs e)
|
/// <summary>
|
||||||
|
/// Opens the settings page. Also disposes of the browser if there is one opened and all thos things
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void btnSettings_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (Emulator != null)
|
if (Emulator != null)
|
||||||
Emulator.ResetDriver();
|
Emulator.ResetDriver();
|
||||||
@@ -88,6 +101,7 @@ namespace TrackTrends
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//Should technically never show up but we never know
|
||||||
MessageBox.Show("The config file has not been found please return to the config and change it");
|
MessageBox.Show("The config file has not been found please return to the config and change it");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,7 +111,11 @@ namespace TrackTrends
|
|||||||
//MessageBox.Show("There is no URL for the Grand Prix you want to decode. Please return to the config and add a valid one");
|
//MessageBox.Show("There is no URL for the Grand Prix you want to decode. Please return to the config and add a valid one");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will do everything that needs to be done at the first start of the app
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private async void Form1_Load(object sender, EventArgs e)
|
private async void Form1_Load(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
//Those are the default values but they will need to be changed later when the configuration has been done
|
//Those are the default values but they will need to be changed later when the configuration has been done
|
||||||
@@ -106,6 +124,8 @@ namespace TrackTrends
|
|||||||
|
|
||||||
tbxGpUrl.Text = GpUrl;
|
tbxGpUrl.Text = GpUrl;
|
||||||
|
|
||||||
|
this.DoubleBuffered = true;
|
||||||
|
|
||||||
oldSize = this.Size;
|
oldSize = this.Size;
|
||||||
oldRankingSize = gpbxRanking.Size;
|
oldRankingSize = gpbxRanking.Size;
|
||||||
oldLapTimesSize = gpbxLapTimes.Size;
|
oldLapTimesSize = gpbxLapTimes.Size;
|
||||||
@@ -134,7 +154,11 @@ namespace TrackTrends
|
|||||||
|
|
||||||
RefreshUI();
|
RefreshUI();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will start or stop the process of decoding
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private async void btnUpdate_Click(object sender, EventArgs e)
|
private async void btnUpdate_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
cancelRequested = false;
|
cancelRequested = false;
|
||||||
@@ -192,18 +216,32 @@ namespace TrackTrends
|
|||||||
btnSettings.Enabled = true;
|
btnSettings.Enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will display the overtakes in the overtakes list box
|
||||||
|
/// </summary>
|
||||||
private void DisplayOvertakes()
|
private void DisplayOvertakes()
|
||||||
{
|
{
|
||||||
Wrapper.DisplayOvertakes(lsbOvertakes);
|
Wrapper.DisplayOvertakes(lsbOvertakes);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will display the battles in the battles pannel
|
||||||
|
/// </summary>
|
||||||
private void DisplayBattles()
|
private void DisplayBattles()
|
||||||
{
|
{
|
||||||
Wrapper.DisplayBattles(pnlBattles, this);
|
Wrapper.DisplayBattles(pnlBattles, this);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will display the time differences in the faster and slowest pannels
|
||||||
|
/// </summary>
|
||||||
private void DisplayDeltas()
|
private void DisplayDeltas()
|
||||||
{
|
{
|
||||||
Wrapper.DisplayTimesDeltas(pnlFastest, pnlSlowest, this);
|
Wrapper.DisplayTimesDeltas(pnlFastest, pnlSlowest, this);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will try to stop the emulator (usually does not work please do not count on it)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
|
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
{
|
{
|
||||||
if (Emulator != null)
|
if (Emulator != null)
|
||||||
@@ -211,6 +249,12 @@ namespace TrackTrends
|
|||||||
Emulator.Stop();
|
Emulator.Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will display the live ranking on the live ranking pannel. Its called like this because historically it was the method that just recovered the bare results from the OCR
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="errorCode"></param>
|
||||||
|
/// <param name="sw"></param>
|
||||||
|
/// <param name="screen"></param>
|
||||||
private void DisplayResults(int errorCode, Stopwatch sw, Bitmap screen)
|
private void DisplayResults(int errorCode, Stopwatch sw, Bitmap screen)
|
||||||
{
|
{
|
||||||
if (errorCode != 0)
|
if (errorCode != 0)
|
||||||
@@ -224,6 +268,11 @@ namespace TrackTrends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will stop the data recovering operation and resets some buttons and text
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void btnStopUpdating_Click(object sender, EventArgs e)
|
private void btnStopUpdating_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// Set the cancellation flag
|
// Set the cancellation flag
|
||||||
@@ -232,6 +281,11 @@ namespace TrackTrends
|
|||||||
btnResetEmulator.Enabled = false;
|
btnResetEmulator.Enabled = false;
|
||||||
btnStopUpdating.Text = "Stopping";
|
btnStopUpdating.Text = "Stopping";
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will start the F1TVEmulator, again this name is historical because back at the start of this project this button did not have a name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private async void button1_Click(object sender, EventArgs e)
|
private async void button1_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
lsbOvertakes.Items.Clear();
|
lsbOvertakes.Items.Clear();
|
||||||
@@ -301,6 +355,11 @@ namespace TrackTrends
|
|||||||
btnStartDecoding.Enabled = true;
|
btnStartDecoding.Enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Silly way to remove borders from groupbox and make them look like pannels with titles
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void removeBorders(object sender, PaintEventArgs e)
|
private void removeBorders(object sender, PaintEventArgs e)
|
||||||
{
|
{
|
||||||
GroupBox gpbx = (GroupBox)sender;
|
GroupBox gpbx = (GroupBox)sender;
|
||||||
@@ -317,17 +376,31 @@ namespace TrackTrends
|
|||||||
e.Graphics.DrawString(gpbx.Text, gpbx.Font, brush, textPosition);
|
e.Graphics.DrawString(gpbx.Text, gpbx.Font, brush, textPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will change the preset to use when starting the emulator
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void lsbPresets_SelectedIndexChanged(object sender, EventArgs e)
|
private void lsbPresets_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (lsbPresets.SelectedIndex >= 0)
|
if (lsbPresets.SelectedIndex >= 0)
|
||||||
ConfigFile = lsbPresets.Items[lsbPresets.SelectedIndex].ToString();
|
ConfigFile = lsbPresets.Items[lsbPresets.SelectedIndex].ToString();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will change the URL the emulator will use, historical name again
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void textBox1_TextChanged(object sender, EventArgs e)
|
private void textBox1_TextChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (tbxGpUrl.Text != "")
|
if (tbxGpUrl.Text != "")
|
||||||
GpUrl = tbxGpUrl.Text;
|
GpUrl = tbxGpUrl.Text;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// This is called by the automatically generated buttons. Its here to fill in the driver info tab whenever the user clicks on a button that contains the name of a driver
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
public void btnDriver_Click(object sender, EventArgs e)
|
public void btnDriver_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
//Removes the cover
|
//Removes the cover
|
||||||
@@ -381,6 +454,11 @@ namespace TrackTrends
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// This is supposed to be called by an automatically generated button. It should be any button with a laptime info on it
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
public void btnLapTime_Click(object sender, EventArgs e)
|
public void btnLapTime_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
//Happens when a lapTime has been clicked
|
//Happens when a lapTime has been clicked
|
||||||
@@ -388,7 +466,11 @@ namespace TrackTrends
|
|||||||
string[] parts = btn.Name.Split('_');
|
string[] parts = btn.Name.Split('_');
|
||||||
Wrapper.DisplayLapTimeInfos(parts[0], Convert.ToInt32(parts[1]), btn.Text);
|
Wrapper.DisplayLapTimeInfos(parts[0], Convert.ToInt32(parts[1]), btn.Text);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will trigger responsive calculation everytime the form changes size
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void Main_Resize(object sender, EventArgs e)
|
private void Main_Resize(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
int xDiff = this.Width - oldSize.Width;
|
int xDiff = this.Width - oldSize.Width;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : OcrImage.cs
|
/// File : OcrImage.cs
|
||||||
/// Brief : Class containing all the methods used to enhance images for OCR
|
/// Brief : Class containing all the methods used to enhance images for OCR
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -19,6 +19,8 @@ namespace TrackTrends
|
|||||||
//Any color that has any of its R,G or B channel higher than the treshold will be considered as being usefull information
|
//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);
|
public static Color F1TV_BACKGROUND_TRESHOLD = Color.FromArgb(0x50, 0x50, 0x50);
|
||||||
Bitmap InputBitmap;
|
Bitmap InputBitmap;
|
||||||
|
|
||||||
|
Random rnd = new Random();
|
||||||
public enum WindowType
|
public enum WindowType
|
||||||
{
|
{
|
||||||
LapTime,
|
LapTime,
|
||||||
@@ -41,7 +43,7 @@ namespace TrackTrends
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type">The type of the window. Depending on it different enhancing features will be applied</param>
|
/// <param name="type">The type of the window. Depending on it different enhancing features will be applied</param>
|
||||||
/// <returns>The enhanced Bitmap</returns>
|
/// <returns>The enhanced Bitmap</returns>
|
||||||
public Bitmap Enhance(int id,WindowType type = WindowType.Text)
|
public Bitmap Enhance(WindowType type = WindowType.Text)
|
||||||
{
|
{
|
||||||
Bitmap outputBitmap = (Bitmap)InputBitmap.Clone();
|
Bitmap outputBitmap = (Bitmap)InputBitmap.Clone();
|
||||||
//Note : If you plan to activate all the comments that I used to debug the OCR I would advise to make sure that the debug folder exists
|
//Note : If you plan to activate all the comments that I used to debug the OCR I would advise to make sure that the debug folder exists
|
||||||
@@ -108,22 +110,29 @@ namespace TrackTrends
|
|||||||
public static Bitmap Grayscale(Bitmap inputBitmap)
|
public static Bitmap Grayscale(Bitmap inputBitmap)
|
||||||
{
|
{
|
||||||
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
|
||||||
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
BitmapData bmpData = inputBitmap.LockBits(rect, ImageLockMode.ReadOnly, inputBitmap.PixelFormat);
|
||||||
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||||
|
|
||||||
|
Bitmap resultBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height);
|
||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
byte* inputPtr = (byte*)bmpData.Scan0.ToPointer();
|
||||||
for (int y = 0; y < inputBitmap.Height; y++)
|
byte* resultPtr = (byte*)resultBitmap.LockBits(rect, ImageLockMode.WriteOnly, resultBitmap.PixelFormat).Scan0.ToPointer();
|
||||||
|
|
||||||
|
Parallel.For(0, inputBitmap.Height, y =>
|
||||||
{
|
{
|
||||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
byte* currentLine = inputPtr + (y * bmpData.Stride);
|
||||||
|
byte* resultLine = resultPtr + (y * resultBitmap.Width * bytesPerPixel);
|
||||||
|
|
||||||
for (int x = 0; x < inputBitmap.Width; x++)
|
for (int x = 0; x < inputBitmap.Width; x++)
|
||||||
{
|
{
|
||||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
byte* inputPixel = currentLine + (x * bytesPerPixel);
|
||||||
|
byte* resultPixel = resultLine + (x * bytesPerPixel);
|
||||||
|
|
||||||
byte blue = pixel[0];
|
byte blue = inputPixel[0];
|
||||||
byte green = pixel[1];
|
byte green = inputPixel[1];
|
||||||
byte red = pixel[2];
|
byte red = inputPixel[2];
|
||||||
|
|
||||||
//Those a specific values to correct the weights so its more pleasing to the human eye
|
//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 gray = (int)(red * 0.3 + green * 0.59 + blue * 0.11);
|
||||||
@@ -131,19 +140,23 @@ namespace TrackTrends
|
|||||||
//This is not a proper treshold method but it is helping the sobel edge detection
|
//This is not a proper treshold method but it is helping the sobel edge detection
|
||||||
if (gray <= F1TV_BACKGROUND_TRESHOLD.R)
|
if (gray <= F1TV_BACKGROUND_TRESHOLD.R)
|
||||||
{
|
{
|
||||||
pixel[0] = pixel[1] = pixel[2] = 0;
|
resultPixel[0] = resultPixel[1] = resultPixel[2] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pixel[0] = pixel[1] = pixel[2] = (byte)gray;
|
resultPixel[0] = resultPixel[1] = resultPixel[2] = (byte)gray;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
resultBitmap.UnlockBits(resultBitmap.LockBits(rect, ImageLockMode.WriteOnly, resultBitmap.PixelFormat));
|
||||||
}
|
}
|
||||||
|
|
||||||
inputBitmap.UnlockBits(bmpData);
|
inputBitmap.UnlockBits(bmpData);
|
||||||
|
|
||||||
return inputBitmap;
|
return resultBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Method that uses the Sobel Edge detection to outline the edges of the characters to help with the OCR
|
/// Method that uses the Sobel Edge detection to outline the edges of the characters to help with the OCR
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -161,6 +174,7 @@ namespace TrackTrends
|
|||||||
|
|
||||||
// Apply the Sobel operators and normalize the gradients
|
// Apply the Sobel operators and normalize the gradients
|
||||||
// NOTE: I dont know how easy or hard it would be to make this paralel but it could be a good idea to do so if possible.
|
// NOTE: I dont know how easy or hard it would be to make this paralel but it could be a good idea to do so if possible.
|
||||||
|
//Parallel.For(1, grayscaleImage.Height - 1, y =>
|
||||||
for (int y = 1; y < grayscaleImage.Height - 1; y++)
|
for (int y = 1; y < grayscaleImage.Height - 1; y++)
|
||||||
{
|
{
|
||||||
for (int x = 1; x < grayscaleImage.Width - 1; x++)
|
for (int x = 1; x < grayscaleImage.Width - 1; x++)
|
||||||
@@ -175,7 +189,7 @@ namespace TrackTrends
|
|||||||
|
|
||||||
edgesImage.SetPixel(x, y, Color.FromArgb(gradient, gradient, gradient));
|
edgesImage.SetPixel(x, y, Color.FromArgb(gradient, gradient, gradient));
|
||||||
}
|
}
|
||||||
}
|
}//);
|
||||||
|
|
||||||
return edgesImage;
|
return edgesImage;
|
||||||
}
|
}
|
||||||
@@ -207,38 +221,36 @@ namespace TrackTrends
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="inputBitmap">The bitmap to vanish</param>
|
/// <param name="inputBitmap">The bitmap to vanish</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Bitmap VanishOxyAction(Bitmap inputBitmap)
|
public Bitmap VanishOxyAction(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
|
unsafe
|
||||||
{
|
{
|
||||||
//Note : MAKE THIS PARALELL OMG WY DID I LEFT IT LIKE THAT
|
BitmapData bitmapData = inputBitmap.LockBits(new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height), ImageLockMode.ReadWrite, inputBitmap.PixelFormat);
|
||||||
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 blue = (int)pixel[0];
|
int bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(inputBitmap.PixelFormat) / 8;
|
||||||
int green = (int)pixel[1];
|
int heightInPixels = bitmapData.Height;
|
||||||
int red = (int)pixel[2];
|
int widthInBytes = bitmapData.Width * bytesPerPixel;
|
||||||
|
byte* PtrFirstPixel = (byte*)bitmapData.Scan0;
|
||||||
|
|
||||||
|
Parallel.For(0, heightInPixels, y =>
|
||||||
|
{
|
||||||
|
byte* currentLine = PtrFirstPixel + (y * bitmapData.Stride);
|
||||||
|
for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
|
||||||
|
{
|
||||||
|
int blue = currentLine[x];
|
||||||
|
int green = currentLine[x + 1];
|
||||||
|
int red = currentLine[x + 2];
|
||||||
|
|
||||||
int max = Math.Max(Math.Max(blue, green), red);
|
int max = Math.Max(Math.Max(blue, green), red);
|
||||||
|
|
||||||
if (max > 255 / 3)
|
if (max > 255 / 3)
|
||||||
max = 255;
|
max = 255;
|
||||||
|
|
||||||
pixel[0] = pixel[1] = pixel[2] = (byte)max;
|
currentLine[x] = currentLine[x + 1] = currentLine[x + 2] = (byte)max;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
inputBitmap.UnlockBits(bitmapData);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
inputBitmap.UnlockBits(bmpData);
|
|
||||||
|
|
||||||
return inputBitmap;
|
return inputBitmap;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -294,10 +306,12 @@ namespace TrackTrends
|
|||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
|
||||||
for (int y = 0; y < inputBitmap.Height; y++)
|
int bmpHeight = inputBitmap.Height;
|
||||||
|
int bmpWidth = inputBitmap.Width;
|
||||||
|
Parallel.For(0, bmpHeight, y =>
|
||||||
{
|
{
|
||||||
byte* currentLine = ptr + (y * bmpData.Stride);
|
byte* currentLine = ptr + (y * bmpData.Stride);
|
||||||
for (int x = 0; x < inputBitmap.Width; x++)
|
for (int x = 0; x < bmpWidth; x++)
|
||||||
{
|
{
|
||||||
byte* pixel = currentLine + (x * bytesPerPixel);
|
byte* pixel = currentLine + (x * bytesPerPixel);
|
||||||
|
|
||||||
@@ -308,7 +322,7 @@ namespace TrackTrends
|
|||||||
if (R <= F1TV_BACKGROUND_TRESHOLD.R && G <= F1TV_BACKGROUND_TRESHOLD.G && B <= F1TV_BACKGROUND_TRESHOLD.B)
|
if (R <= F1TV_BACKGROUND_TRESHOLD.R && G <= F1TV_BACKGROUND_TRESHOLD.G && B <= F1TV_BACKGROUND_TRESHOLD.B)
|
||||||
pixel[0] = pixel[1] = pixel[2] = 0;
|
pixel[0] = pixel[1] = pixel[2] = 0;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
inputBitmap.UnlockBits(bmpData);
|
inputBitmap.UnlockBits(bmpData);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : Reader.cs
|
/// File : Reader.cs
|
||||||
/// Brief : Class used to Read the config file for the OCR
|
/// Brief : Class used to Read the config file for the OCR
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|||||||
@@ -294,7 +294,6 @@
|
|||||||
this.pbxPreview.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
|
this.pbxPreview.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
|
||||||
this.pbxPreview.TabIndex = 0;
|
this.pbxPreview.TabIndex = 0;
|
||||||
this.pbxPreview.TabStop = false;
|
this.pbxPreview.TabStop = false;
|
||||||
this.pbxPreview.Click += new System.EventHandler(this.pbxMain_Click);
|
|
||||||
this.pbxPreview.MouseClick += new System.Windows.Forms.MouseEventHandler(this.pbxMain_MouseClick);
|
this.pbxPreview.MouseClick += new System.Windows.Forms.MouseEventHandler(this.pbxMain_MouseClick);
|
||||||
//
|
//
|
||||||
// btnCreatZone
|
// btnCreatZone
|
||||||
@@ -337,7 +336,6 @@
|
|||||||
this.pbxWindowPreview.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
|
this.pbxWindowPreview.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
|
||||||
this.pbxWindowPreview.TabIndex = 0;
|
this.pbxWindowPreview.TabIndex = 0;
|
||||||
this.pbxWindowPreview.TabStop = false;
|
this.pbxWindowPreview.TabStop = false;
|
||||||
this.pbxWindowPreview.Click += new System.EventHandler(this.pbxDriverZone_Click);
|
|
||||||
this.pbxWindowPreview.MouseClick += new System.Windows.Forms.MouseEventHandler(this.pbxDriverZone_MouseClick);
|
this.pbxWindowPreview.MouseClick += new System.Windows.Forms.MouseEventHandler(this.pbxDriverZone_MouseClick);
|
||||||
//
|
//
|
||||||
// btnLoadPreset
|
// btnLoadPreset
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
using System;
|
/// Author : Maxime Rohmer
|
||||||
|
/// Date : 09/06/2023
|
||||||
|
/// File : Settings.cs
|
||||||
|
/// Brief : Class that controls the settings view
|
||||||
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
@@ -48,6 +54,9 @@ namespace TrackTrends
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// This methods regroups all the actions that the forms need to be doing at the first launch
|
||||||
|
/// </summary>
|
||||||
private void Load()
|
private void Load()
|
||||||
{
|
{
|
||||||
RefreshUI();
|
RefreshUI();
|
||||||
@@ -57,6 +66,11 @@ namespace TrackTrends
|
|||||||
oldPbxPreviewSize = pbxPreview.Size;
|
oldPbxPreviewSize = pbxPreview.Size;
|
||||||
oldPbxWindowPreviewSize = pbxWindowPreview.Size;
|
oldPbxWindowPreviewSize = pbxWindowPreview.Size;
|
||||||
|
|
||||||
|
btnLoadPreset.Enabled = false;
|
||||||
|
btnDeletePreset.Enabled = false;
|
||||||
|
btnSavePreset.Enabled = false;
|
||||||
|
|
||||||
|
// I prefered regrouping all the tooltips here to make it easier to edit (there is 100% of thoses sentences containing typos so if you see one dont hesitate to edit those messages)
|
||||||
tip1.SetToolTip(btnCreatZone, "After clicking you can select two points in the image to set the bounds of the important data");
|
tip1.SetToolTip(btnCreatZone, "After clicking you can select two points in the image to set the bounds of the important data");
|
||||||
tip1.SetToolTip(btnCreateWindow, "After clicking this you will have to select all the windows that are important on the lower image. Refer to the documentation for more infos");
|
tip1.SetToolTip(btnCreateWindow, "After clicking this you will have to select all the windows that are important on the lower image. Refer to the documentation for more infos");
|
||||||
tip1.SetToolTip(btnRefresh, "Starts the emulator or refreshes the images if its already running");
|
tip1.SetToolTip(btnRefresh, "Starts the emulator or refreshes the images if its already running");
|
||||||
@@ -66,6 +80,10 @@ namespace TrackTrends
|
|||||||
tip1.SetToolTip(pbxPreview, "What the emulator returns");
|
tip1.SetToolTip(pbxPreview, "What the emulator returns");
|
||||||
tip1.SetToolTip(pbxWindowPreview, "One of the driver zones that the program managed to slice from the main zone");
|
tip1.SetToolTip(pbxWindowPreview, "One of the driver zones that the program managed to slice from the main zone");
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// This is the main method that will be called anytime something changes on the view
|
||||||
|
/// It can be called at any time and will adapt the UI taking into account the state of the app
|
||||||
|
/// </summary>
|
||||||
private void RefreshUI()
|
private void RefreshUI()
|
||||||
{
|
{
|
||||||
lsbDrivers.DataSource = null;
|
lsbDrivers.DataSource = null;
|
||||||
@@ -116,12 +134,21 @@ namespace TrackTrends
|
|||||||
pbxWindowPreview.Image = Config.MainZone.Zones[0].Draw();
|
pbxWindowPreview.Image = Config.MainZone.Zones[0].Draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// This will create a new zone but will require two points (one at each opposing sides and corners)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p1">The first corner (usually top left)</param>
|
||||||
|
/// <param name="p2">The second corner (usually bottom right)</param>
|
||||||
private void CreateNewZone(Point p1, Point p2)
|
private void CreateNewZone(Point p1, Point p2)
|
||||||
{
|
{
|
||||||
Rectangle dimensions = CreateAbsoluteRectangle(p1, p2);
|
Rectangle dimensions = CreateAbsoluteRectangle(p1, p2);
|
||||||
Config = new ConfigurationTool((Bitmap)pbxPreview.Image, dimensions);
|
Config = new ConfigurationTool((Bitmap)pbxPreview.Image, dimensions);
|
||||||
RefreshUI();
|
RefreshUI();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Creates all the windows with an array of rectangles
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dimensions">An array that contains all the windows bounds and position (expects 9)</param>
|
||||||
private void CreateWindows(List<Rectangle> dimensions)
|
private void CreateWindows(List<Rectangle> dimensions)
|
||||||
{
|
{
|
||||||
if (Config != null)
|
if (Config != null)
|
||||||
@@ -129,11 +156,20 @@ namespace TrackTrends
|
|||||||
Config.AddWindows(dimensions);
|
Config.AddWindows(dimensions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will just change the main URL
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void tbxGpUrl_TextChanged(object sender, EventArgs e)
|
private void tbxGpUrl_TextChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
GrandPrixUrl = tbxGpUrl.Text;
|
GrandPrixUrl = tbxGpUrl.Text;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a driver into the driver list
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void btnAddDriver_Click(object sender, EventArgs e)
|
private void btnAddDriver_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
string newDriver = tbxDriverName.Text;
|
string newDriver = tbxDriverName.Text;
|
||||||
@@ -141,7 +177,11 @@ namespace TrackTrends
|
|||||||
tbxDriverName.Text = "";
|
tbxDriverName.Text = "";
|
||||||
RefreshUI();
|
RefreshUI();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a driver from the drivers list
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void btnRemoveDriver_Click(object sender, EventArgs e)
|
private void btnRemoveDriver_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (lsbDrivers.SelectedIndex >= 0)
|
if (lsbDrivers.SelectedIndex >= 0)
|
||||||
@@ -150,6 +190,9 @@ namespace TrackTrends
|
|||||||
}
|
}
|
||||||
RefreshUI();
|
RefreshUI();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will change everything that needs to be changed for when the users starts or stops creating a zone
|
||||||
|
/// </summary>
|
||||||
private void SwitchZoneCreation()
|
private void SwitchZoneCreation()
|
||||||
{
|
{
|
||||||
if (CreatingZone)
|
if (CreatingZone)
|
||||||
@@ -180,6 +223,9 @@ namespace TrackTrends
|
|||||||
}
|
}
|
||||||
RefreshUI();
|
RefreshUI();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will change everything that needs to be changed for when the users starts or stops creating a window
|
||||||
|
/// </summary>
|
||||||
private void SwitchWindowCreation()
|
private void SwitchWindowCreation()
|
||||||
{
|
{
|
||||||
if (CreatingWindow)
|
if (CreatingWindow)
|
||||||
@@ -211,6 +257,11 @@ namespace TrackTrends
|
|||||||
{
|
{
|
||||||
SwitchWindowCreation();
|
SwitchWindowCreation();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// If the user is supposed to create a zone, will record the position of the clicks
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void pbxMain_MouseClick(object sender, MouseEventArgs e)
|
private void pbxMain_MouseClick(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
if (CreatingZone && pbxPreview.Image != null)
|
if (CreatingZone && pbxPreview.Image != null)
|
||||||
@@ -236,10 +287,11 @@ namespace TrackTrends
|
|||||||
RefreshUI();
|
RefreshUI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void pbxMain_Click(object sender, EventArgs e)
|
/// <summary>
|
||||||
{
|
/// If the user is supposed to create a window, will record the position of the clicks
|
||||||
//Not the right one to use visibly
|
/// </summary>
|
||||||
}
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void pbxDriverZone_MouseClick(object sender, MouseEventArgs e)
|
private void pbxDriverZone_MouseClick(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
if (CreatingWindow && pbxWindowPreview.Image != null)
|
if (CreatingWindow && pbxWindowPreview.Image != null)
|
||||||
@@ -276,15 +328,18 @@ namespace TrackTrends
|
|||||||
RefreshUI();
|
RefreshUI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void pbxDriverZone_Click(object sender, EventArgs e)
|
/// <summary>
|
||||||
{
|
/// Creates a rectangle without caring about the order of the points.
|
||||||
//Not the right one to use visibly
|
/// </summary>
|
||||||
}
|
/// <param name="p1">First point. Can be top left or bottom right</param>
|
||||||
|
/// <param name="p2">Second point. Can be top left or bottom right</param>
|
||||||
|
/// <returns></returns>
|
||||||
private Rectangle CreateAbsoluteRectangle(Point p1, Point p2)
|
private Rectangle CreateAbsoluteRectangle(Point p1, Point p2)
|
||||||
{
|
{
|
||||||
Point newP1 = new Point();
|
Point newP1 = new Point();
|
||||||
Point newP2 = new Point();
|
Point newP2 = new Point();
|
||||||
|
|
||||||
|
//Kind of a pain to have to do this but this lets the user do stupid things without the app crashing
|
||||||
if (p1.X < p2.X)
|
if (p1.X < p2.X)
|
||||||
{
|
{
|
||||||
newP1.X = p1.X;
|
newP1.X = p1.X;
|
||||||
@@ -308,7 +363,11 @@ namespace TrackTrends
|
|||||||
}
|
}
|
||||||
return new Rectangle(newP1.X, newP1.Y, newP2.X - newP1.X, newP2.Y - newP1.Y);
|
return new Rectangle(newP1.X, newP1.Y, newP2.X - newP1.X, newP2.Y - newP1.Y);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will refresh the emulator and will controll some of the controls
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private async void btnRefresh_Click(object sender, EventArgs e)
|
private async void btnRefresh_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
btnRefresh.Enabled = false;
|
btnRefresh.Enabled = false;
|
||||||
@@ -355,23 +414,45 @@ namespace TrackTrends
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
MessageBox.Show(message);
|
MessageBox.Show(message);
|
||||||
|
btnRefresh.Text = "Retry";
|
||||||
|
btnLoadPreset.Enabled = false;
|
||||||
|
btnDeletePreset.Enabled = false;
|
||||||
|
btnSavePreset.Enabled = false;
|
||||||
|
btnCreatZone.Enabled = false;
|
||||||
|
btnCreateWindow.Enabled = false;
|
||||||
|
btnResetDriver.Enabled = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
btnRefresh.Text = "Get a newer image";
|
||||||
pbxPreview.Image = Emulator.Screenshot();
|
pbxPreview.Image = Emulator.Screenshot();
|
||||||
}
|
|
||||||
}
|
btnLoadPreset.Enabled = true;
|
||||||
else
|
btnDeletePreset.Enabled = true;
|
||||||
{
|
btnSavePreset.Enabled = true;
|
||||||
pbxPreview.Image = Emulator.Screenshot();
|
|
||||||
}
|
|
||||||
btnRefresh.Enabled = true;
|
|
||||||
btnCreatZone.Enabled = true;
|
btnCreatZone.Enabled = true;
|
||||||
btnCreateWindow.Enabled = true;
|
btnCreateWindow.Enabled = true;
|
||||||
btnResetDriver.Enabled = true;
|
btnResetDriver.Enabled = true;
|
||||||
btnRefresh.Text = "Get a newer image";
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pbxPreview.Image = Emulator.Screenshot();
|
||||||
|
//I know im repeating myself. This part could use a bool variable that allows those buttons to be displayed but it was the fastest way to fix a bad behaviour in the app
|
||||||
|
btnLoadPreset.Enabled = true;
|
||||||
|
btnDeletePreset.Enabled = true;
|
||||||
|
btnSavePreset.Enabled = true;
|
||||||
|
btnCreatZone.Enabled = true;
|
||||||
|
btnCreateWindow.Enabled = true;
|
||||||
|
btnResetDriver.Enabled = true;
|
||||||
|
}
|
||||||
|
btnRefresh.Enabled = true;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will try to close the headless browser so the main form can launch a new one safely
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void Settings_FormClosing(object sender, FormClosingEventArgs e)
|
private void Settings_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
{
|
{
|
||||||
if (Emulator != null)
|
if (Emulator != null)
|
||||||
@@ -381,7 +462,11 @@ namespace TrackTrends
|
|||||||
Emulator = null;
|
Emulator = null;
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will reset the drivers
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void btnResetDriver_Click(object sender, EventArgs e)
|
private void btnResetDriver_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (Emulator != null)
|
if (Emulator != null)
|
||||||
@@ -389,7 +474,11 @@ namespace TrackTrends
|
|||||||
Emulator.ResetDriver();
|
Emulator.ResetDriver();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Saves the current presets as a new JSON file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void btnSavePreset_Click(object sender, EventArgs e)
|
private void btnSavePreset_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
string presetName = tbxPresetName.Text;
|
string presetName = tbxPresetName.Text;
|
||||||
@@ -399,12 +488,21 @@ namespace TrackTrends
|
|||||||
}
|
}
|
||||||
RefreshUI();
|
RefreshUI();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will change the selected preset. Usefull if you close this page because then the main form will keep in memory your last choice
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void lsbPresets_SelectedIndexChanged(object sender, EventArgs e)
|
private void lsbPresets_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
if (lsbPresets.SelectedIndex >= 0)
|
||||||
SelectedConfigFile = (string)lsbPresets.Items[lsbPresets.SelectedIndex];
|
SelectedConfigFile = (string)lsbPresets.Items[lsbPresets.SelectedIndex];
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will load an existing presets
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void btnLoadPreset_Click(object sender, EventArgs e)
|
private void btnLoadPreset_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
//MessageBox.Show(lsbPresets.SelectedIndex.ToString());
|
//MessageBox.Show(lsbPresets.SelectedIndex.ToString());
|
||||||
@@ -427,7 +525,11 @@ namespace TrackTrends
|
|||||||
RefreshUI();
|
RefreshUI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// This will be called everytime the form resizes. Here we are making the form responsive
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void Settings_Resize(object sender, EventArgs e)
|
private void Settings_Resize(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
int xDiff = this.Width - oldSize.Width;
|
int xDiff = this.Width - oldSize.Width;
|
||||||
@@ -438,7 +540,11 @@ namespace TrackTrends
|
|||||||
pbxPreview.Size = new Size(oldPbxPreviewSize.Width + xDiff, oldPbxPreviewSize.Height + yDiff);
|
pbxPreview.Size = new Size(oldPbxPreviewSize.Width + xDiff, oldPbxPreviewSize.Height + yDiff);
|
||||||
pbxWindowPreview.Size = new Size(oldPbxWindowPreviewSize.Width + xDiff, oldPbxWindowPreviewSize.Height);
|
pbxWindowPreview.Size = new Size(oldPbxWindowPreviewSize.Width + xDiff, oldPbxWindowPreviewSize.Height);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Will delete an existing preset
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void btnDeletePreset_Click(object sender, EventArgs e)
|
private void btnDeletePreset_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
int selectedIndex = lsbPresets.SelectedIndex;
|
int selectedIndex = lsbPresets.SelectedIndex;
|
||||||
@@ -456,7 +562,11 @@ namespace TrackTrends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Sketchy method that is used to remove the borders from groupboxes... Yes its dumb but I dont think there is any other way
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
private void removeBorders(object sender, PaintEventArgs e)
|
private void removeBorders(object sender, PaintEventArgs e)
|
||||||
{
|
{
|
||||||
GroupBox gpbx = (GroupBox)sender;
|
GroupBox gpbx = (GroupBox)sender;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/08/2023
|
||||||
/// File : SqliteStorage.cs
|
/// File : SqliteStorage.cs
|
||||||
/// Brief : Class that controls the sqlite database
|
/// Brief : Class that controls the sqlite database
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : Window.cs
|
/// File : Window.cs
|
||||||
/// Brief : Default Window object that is mainly expected to be inherited.
|
/// Brief : Default Window object that is mainly expected to be inherited.
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -153,7 +153,7 @@ namespace TrackTrends
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Bitmap enhancedImage = new OcrImage(image).Enhance(salt, windowType);
|
Bitmap enhancedImage = new OcrImage(image).Enhance(windowType);
|
||||||
|
|
||||||
var tessImage = Pix.LoadFromMemory(ImageToByte(enhancedImage));
|
var tessImage = Pix.LoadFromMemory(ImageToByte(enhancedImage));
|
||||||
|
|
||||||
@@ -529,6 +529,10 @@ namespace TrackTrends
|
|||||||
// This should be the x:xx.xxx
|
// This should be the x:xx.xxx
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
//Gaps cant be more than 9 minuts so if there is more than 1 digit it means that the '+' has been understood as an other number
|
||||||
|
if (rawNumbers[0].Length > 1)
|
||||||
|
rawNumbers[0] = rawNumbers[0][rawNumbers[0].Length - 1].ToString();
|
||||||
|
|
||||||
minuts = Convert.ToInt32(rawNumbers[0].ToString());
|
minuts = Convert.ToInt32(rawNumbers[0].ToString());
|
||||||
seconds = Convert.ToInt32(rawNumbers[1].ToString());
|
seconds = Convert.ToInt32(rawNumbers[1].ToString());
|
||||||
miliseconds = Convert.ToInt32(rawNumbers[2].ToString());
|
miliseconds = Convert.ToInt32(rawNumbers[2].ToString());
|
||||||
@@ -578,7 +582,7 @@ namespace TrackTrends
|
|||||||
Engine.SetVariable("tessedit_char_whitelist", allowedChars);
|
Engine.SetVariable("tessedit_char_whitelist", allowedChars);
|
||||||
|
|
||||||
Bitmap rawData = image;
|
Bitmap rawData = image;
|
||||||
Bitmap enhancedImage = new OcrImage(rawData).Enhance(salt, windowType);
|
Bitmap enhancedImage = new OcrImage(rawData).Enhance(windowType);
|
||||||
|
|
||||||
Page page = Engine.Process(enhancedImage);
|
Page page = Engine.Process(enhancedImage);
|
||||||
using (var iter = page.GetIterator())
|
using (var iter = page.GetIterator())
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/// Author : Maxime Rohmer
|
/// Author : Maxime Rohmer
|
||||||
/// Date : 30/05/2023
|
/// Date : 09/06/2023
|
||||||
/// File : Zone.cs
|
/// File : Zone.cs
|
||||||
/// Brief : Class that contains all the methods and infos for a zone. This is designed to be potentially be inherited.
|
/// Brief : Class that contains all the methods and infos for a zone. This is designed to be potentially be inherited.
|
||||||
/// Version : Alpha 1.0
|
/// Version : Beta 1.0
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|||||||
@@ -0,0 +1,260 @@
|
|||||||
|
/// Author : Maxime Rohmer
|
||||||
|
/// Date : 01/06/2023
|
||||||
|
/// File : OcrImageTests.cs
|
||||||
|
/// Brief : Class that is here to test the working principle of the OCR. Its not really unit test because we dont test a single class
|
||||||
|
/// Version : Alpha 1.0
|
||||||
|
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TrackTrends;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.IO;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace TrackTrends.Tests
|
||||||
|
{
|
||||||
|
[TestClass()]
|
||||||
|
public class OcrImageTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the OCR on LapTimes is working.
|
||||||
|
/// </summary>
|
||||||
|
[TestMethod()]
|
||||||
|
public void LapTimeOCR_Test()
|
||||||
|
{
|
||||||
|
string directory = @"./../../TestImages/LapTimes/";
|
||||||
|
foreach (string file in Directory.GetFiles(directory))
|
||||||
|
{
|
||||||
|
Bitmap image = (Bitmap)Image.FromFile(file);
|
||||||
|
DriverLapTimeWindow lapTimeWindow = new DriverLapTimeWindow(image, new Rectangle(0, 0, image.Width, image.Height), true);
|
||||||
|
string[] paths = file.Split('/');
|
||||||
|
string fileName = paths[paths.Length - 1];
|
||||||
|
fileName = fileName.Replace(".png", "");
|
||||||
|
|
||||||
|
int timeMS = (int)lapTimeWindow.DecodePng();
|
||||||
|
string time = Reader.ConvertMsToTime(timeMS);
|
||||||
|
|
||||||
|
string[] checkDigits = fileName.Split('_');
|
||||||
|
string[] digitsToCheck = time.Split(':');
|
||||||
|
|
||||||
|
//The ConvertMSToTime will always return three chars so we need to make the checkDigits be also three chars
|
||||||
|
while (checkDigits.Length != 3)
|
||||||
|
checkDigits = new[] { "0" }.Concat(checkDigits).ToArray();
|
||||||
|
|
||||||
|
for (int i = 0; i < checkDigits.Length; i++)
|
||||||
|
{
|
||||||
|
Assert.AreEqual(checkDigits[i], digitsToCheck[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the Driver Position is well detected using the OCR
|
||||||
|
/// </summary>
|
||||||
|
[TestMethod()]
|
||||||
|
public void PositionOCR_Test()
|
||||||
|
{
|
||||||
|
string directory = @"./../../TestImages/Positions/";
|
||||||
|
foreach (string file in Directory.GetFiles(directory))
|
||||||
|
{
|
||||||
|
Bitmap image = (Bitmap)Image.FromFile(file);
|
||||||
|
DriverPositionWindow posWindow = new DriverPositionWindow(image, new Rectangle(0, 0, image.Width, image.Height), true);
|
||||||
|
string[] paths = file.Split('/');
|
||||||
|
string fileName = paths[paths.Length - 1];
|
||||||
|
fileName = fileName.Replace(".png", "");
|
||||||
|
|
||||||
|
int foundPos = (int)posWindow.DecodePng();
|
||||||
|
|
||||||
|
Assert.AreEqual(Convert.ToInt32(fileName), foundPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the tyres are correctly recognized using OCR
|
||||||
|
/// </summary>
|
||||||
|
[TestMethod()]
|
||||||
|
public void TyresOCR_Test()
|
||||||
|
{
|
||||||
|
string directory = @"./../../TestImages/Tyres/";
|
||||||
|
foreach (string file in Directory.GetFiles(directory))
|
||||||
|
{
|
||||||
|
Bitmap image = (Bitmap)Image.FromFile(file);
|
||||||
|
DriverTyresWindow tyreWindow = new DriverTyresWindow(image, new Rectangle(0, 0, image.Width, image.Height), true);
|
||||||
|
string[] paths = file.Split('/');
|
||||||
|
string fileName = paths[paths.Length - 1];
|
||||||
|
fileName = fileName.Replace(".png", "");
|
||||||
|
|
||||||
|
string[] fileInfos = fileName.Split('_');
|
||||||
|
string expectedType = fileInfos[0];
|
||||||
|
int expectedLap = Convert.ToInt32(fileInfos[1]);
|
||||||
|
|
||||||
|
Tyre foundTyre = (Tyre)tyreWindow.DecodePng();
|
||||||
|
|
||||||
|
switch (foundTyre.Coumpound)
|
||||||
|
{
|
||||||
|
case Tyre.Type.Soft:
|
||||||
|
Assert.AreEqual("SOFT",expectedType.ToUpper());
|
||||||
|
break;
|
||||||
|
case Tyre.Type.Inter:
|
||||||
|
Assert.AreEqual("INTER", expectedType.ToUpper());
|
||||||
|
break;
|
||||||
|
case Tyre.Type.Hard:
|
||||||
|
Assert.AreEqual("HARD", expectedType.ToUpper());
|
||||||
|
break;
|
||||||
|
case Tyre.Type.Wet:
|
||||||
|
Assert.AreEqual("WET", expectedType.ToUpper());
|
||||||
|
break;
|
||||||
|
case Tyre.Type.Medium:
|
||||||
|
Assert.AreEqual("MEDIUM", expectedType.ToUpper());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Assert.AreEqual(expectedLap,foundTyre.NumberOfLaps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the Gap to the leader is well decoded from the image using the OCR
|
||||||
|
/// </summary>
|
||||||
|
[TestMethod()]
|
||||||
|
public void GapToLeaderOCR_Test()
|
||||||
|
{
|
||||||
|
string directory = @"./../../TestImages/Gaps/";
|
||||||
|
foreach (string file in Directory.GetFiles(directory))
|
||||||
|
{
|
||||||
|
Bitmap image = (Bitmap)Image.FromFile(file);
|
||||||
|
DriverGapToLeaderWindow gapsWindow = new DriverGapToLeaderWindow(image, new Rectangle(0, 0, image.Width, image.Height), true);
|
||||||
|
string[] paths = file.Split('/');
|
||||||
|
string fileName = paths[paths.Length - 1];
|
||||||
|
fileName = fileName.Replace(".png", "");
|
||||||
|
|
||||||
|
int timeMS = (int)gapsWindow.DecodePng();
|
||||||
|
string time = Reader.ConvertMsToTime(timeMS);
|
||||||
|
|
||||||
|
string[] checkDigits = fileName.Split('_');
|
||||||
|
string[] digitsToCheck = time.Split(':');
|
||||||
|
|
||||||
|
if (time == "0:00:000")
|
||||||
|
{
|
||||||
|
Assert.AreEqual(0, Convert.ToInt32(checkDigits[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//The ConvertMSToTime will always return three chars so we need to make the checkDigits be also three chars
|
||||||
|
while (checkDigits.Length != 3)
|
||||||
|
checkDigits = new[] { "0" }.Concat(checkDigits).ToArray();
|
||||||
|
|
||||||
|
for (int i = 0; i < checkDigits.Length; i++)
|
||||||
|
{
|
||||||
|
//We need to convert to int first because sometimes we have "08" and "8" and in string its not the same but in int it is
|
||||||
|
Assert.AreEqual(Convert.ToInt32(checkDigits[i]), Convert.ToInt32(digitsToCheck[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the DRS window is well recognized as open of closed
|
||||||
|
/// </summary>
|
||||||
|
[TestMethod()]
|
||||||
|
public void DRS_OCR_Test()
|
||||||
|
{
|
||||||
|
string directory = @"./../../TestImages/DRS/";
|
||||||
|
DirectoryInfo directoryInfo = new DirectoryInfo(directory);
|
||||||
|
Bitmap falseExemple = (Bitmap)Image.FromFile(directory + "False.png");
|
||||||
|
Bitmap trueExemple = (Bitmap)Image.FromFile(directory + "True.png");
|
||||||
|
|
||||||
|
DriverDrsWindow falseDRS = new DriverDrsWindow(falseExemple, new Rectangle(0, 0, falseExemple.Width, falseExemple.Height), true);
|
||||||
|
DriverDrsWindow trueDRS = new DriverDrsWindow(trueExemple, new Rectangle(0, 0, trueExemple.Width, trueExemple.Height), true);
|
||||||
|
|
||||||
|
bool falseResult = (bool)falseDRS.DecodePng();
|
||||||
|
bool trueResult = (bool)trueDRS.DecodePng();
|
||||||
|
|
||||||
|
Assert.IsFalse(falseResult);
|
||||||
|
Assert.IsTrue(trueResult);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the driver names are recognized correctly
|
||||||
|
/// </summary>
|
||||||
|
[TestMethod()]
|
||||||
|
public void DriverNameOCR_Test()
|
||||||
|
{
|
||||||
|
string directory = @"./../../TestImages/Names/";
|
||||||
|
foreach (string file in Directory.GetFiles(directory))
|
||||||
|
{
|
||||||
|
Bitmap image = (Bitmap)Image.FromFile(file);
|
||||||
|
DriverNameWindow nameWindow = new DriverNameWindow(image, new Rectangle(0, 0, image.Width, image.Height), true);
|
||||||
|
string[] paths = file.Split('/');
|
||||||
|
string fileName = paths[paths.Length - 1];
|
||||||
|
fileName = fileName.Replace(".png", "");
|
||||||
|
|
||||||
|
List<string> driverList = new List<String>();
|
||||||
|
|
||||||
|
driverList.Add("Albon");
|
||||||
|
driverList.Add("Alonso");
|
||||||
|
driverList.Add("Bottas");
|
||||||
|
driverList.Add("De Vries");
|
||||||
|
driverList.Add("Gasly");
|
||||||
|
driverList.Add("Hamilton");
|
||||||
|
driverList.Add("Hulkenberg");
|
||||||
|
driverList.Add("Leclerc");
|
||||||
|
driverList.Add("Magnussen");
|
||||||
|
driverList.Add("Norris");
|
||||||
|
driverList.Add("Ocon");
|
||||||
|
driverList.Add("Perez");
|
||||||
|
driverList.Add("Piastri");
|
||||||
|
driverList.Add("Russel");
|
||||||
|
driverList.Add("Sainz");
|
||||||
|
driverList.Add("Sargeant");
|
||||||
|
driverList.Add("Stroll");
|
||||||
|
driverList.Add("Tsunoda");
|
||||||
|
driverList.Add("Verstappen");
|
||||||
|
driverList.Add("Zhou");
|
||||||
|
|
||||||
|
string foundName = (string)nameWindow.DecodePng(driverList);
|
||||||
|
//We only compare without the case because it does not really matter
|
||||||
|
//We remove the '_' from the file name for cases like "De Vries" wich obviously would be "De_Vries.png" as filename
|
||||||
|
fileName = fileName.Replace('_', ' ');
|
||||||
|
|
||||||
|
Assert.AreEqual(fileName.ToUpper(),foundName.ToUpper());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the Sectors are correctly decoded using the OCR
|
||||||
|
/// </summary>
|
||||||
|
[TestMethod()]
|
||||||
|
public void SectorOCR_Test()
|
||||||
|
{
|
||||||
|
string directory = @"./../../TestImages/Sectors/";
|
||||||
|
foreach (string file in Directory.GetFiles(directory))
|
||||||
|
{
|
||||||
|
Bitmap image = (Bitmap)Image.FromFile(file);
|
||||||
|
DriverSectorWindow sectorsWindow = new DriverSectorWindow(image, new Rectangle(0, 0, image.Width, image.Height), 1, true);
|
||||||
|
string[] paths = file.Split('/');
|
||||||
|
string fileName = paths[paths.Length - 1];
|
||||||
|
fileName = fileName.Replace(".png", "");
|
||||||
|
|
||||||
|
int timeMS = (int)sectorsWindow.DecodePng();
|
||||||
|
string time = Reader.ConvertMsToTime(timeMS);
|
||||||
|
|
||||||
|
string[] checkDigits = fileName.Split('_');
|
||||||
|
string[] digitsToCheck = time.Split(':');
|
||||||
|
|
||||||
|
if (time == "0:00:000")
|
||||||
|
{
|
||||||
|
Assert.AreEqual(0, Convert.ToInt32(checkDigits[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//The ConvertMSToTime will always return three chars so we need to make the checkDigits be also three chars
|
||||||
|
while (checkDigits.Length != 3)
|
||||||
|
checkDigits = new[] { "0" }.Concat(checkDigits).ToArray();
|
||||||
|
|
||||||
|
for (int i = 0; i < checkDigits.Length; i++)
|
||||||
|
{
|
||||||
|
//We need to convert to int first because sometimes we have "08" and "8" and in string its not the same but in int it is
|
||||||
|
Assert.AreEqual(Convert.ToInt32(checkDigits[i]), Convert.ToInt32(digitsToCheck[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("TrackTrendsTests")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("TrackTrendsTests")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("9be68783-f589-479a-8cfa-9652c3b23a37")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.2 KiB |