Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
cadon committed Oct 8, 2022
2 parents 36c7396 + e81a702 commit d7e43e3
Show file tree
Hide file tree
Showing 33 changed files with 708 additions and 316 deletions.
2 changes: 1 addition & 1 deletion ARKBreedingStats/ARKOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void InitLabelPositions()

for (int statIndex = 0; statIndex < _labels.Length; statIndex++)
{
Rectangle r = ArkOcr.Ocr.ocrConfig.labelRectangles[statIndex];
Rectangle r = ArkOcr.Ocr.ocrConfig.UsedLabelRectangles[statIndex];
_labels[statIndex].Location = new Point(r.Left + r.Width + 30, r.Top - 10);
}
lblStatus.Location = new Point(50, 10);
Expand Down
4 changes: 4 additions & 0 deletions ARKBreedingStats/CreatureInfoInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,10 @@ public CreatureFlags CreatureFlags
if (CbMutagen.Checked)
_creatureFlags |= CreatureFlags.MutagenApplied;
else _creatureFlags &= ~CreatureFlags.MutagenApplied;
if (MutationCounterMother > 0 || MutationCounterFather > 0)
_creatureFlags |= CreatureFlags.Mutated;
else _creatureFlags &= ~CreatureFlags.Mutated;

return _creatureFlags;
}
set
Expand Down
99 changes: 63 additions & 36 deletions ARKBreedingStats/Form1.Designer.cs

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion ARKBreedingStats/Form1.collection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
using System.Xml.Serialization;
using ARKBreedingStats.uiControls;
using ARKBreedingStats.utils;
using System.Diagnostics;

namespace ARKBreedingStats
{
Expand Down Expand Up @@ -532,6 +531,13 @@ private bool LoadCollectionFile(string filePath, bool keepCurrentCreatures = fal
// calculate creature values
RecalculateAllCreaturesValues();

foreach (var c in _creatureCollection.creatures)
{
c.InitializeFlags();
if (c.ArkIdImported && c.ArkIdInGame == null)
c.ArkIdInGame = Utils.ConvertImportedArkIdToIngameVisualization(c.ArkId);
}

if (!keepCurrentSelections && _creatureCollection.creatures.Any())
tabControlMain.SelectedTab = tabPageLibrary;

Expand Down
13 changes: 11 additions & 2 deletions ARKBreedingStats/Form1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,14 @@ public Form1()
creatureInfoInputExtractor.SetMessageLabelText += SetMessageLabelText;
creatureInfoInputTester.SetMessageLabelText += SetMessageLabelText;
timerList1.OnTimerChange += SetCollectionChanged;
timerList1.TimerAddedRemoved += EnableGlobalTimerIfNeeded;
breedingPlan1.BindChildrenControlEvents();
raisingControl1.onChange += SetCollectionChanged;
tamingControl1.CreateTimer += CreateTimer;
raisingControl1.ExtractBaby += ExtractBaby;
raisingControl1.SetGlobalSpecies += SetSpecies;
raisingControl1.timerControl = timerList1;
raisingControl1.TimerAddedRemoved += EnableGlobalTimerIfNeeded;
notesControl1.changed += SetCollectionChanged;
creatureInfoInputExtractor.CreatureDataRequested += CreatureInfoInput_CreatureDataRequested;
creatureInfoInputTester.CreatureDataRequested += CreatureInfoInput_CreatureDataRequested;
Expand All @@ -176,6 +178,8 @@ public Form1()
ArkOcr.Ocr.SetOcrControl(ocrControl1);
ocrControl1.UpdateWhiteThreshold += OcrUpdateWhiteThreshold;
ocrControl1.DoOcr += DoOcr;
ocrControl1.OcrLabelSetsChanged += InitializeOcrLabelSets;
ocrControl1.OcrLabelSelectedSetChanged += SetCurrentOcrLabelSet;

openSettingsToolStripMenuItem.ShortcutKeyDisplayString = new KeysConverter()
.ConvertTo(Keys.Control, typeof(string))?.ToString().Replace("None", ",");
Expand Down Expand Up @@ -325,6 +329,7 @@ private void Form1_Load(object sender, EventArgs e)
// OCR
ocrControl1.Initialize();
cbGuessSpecies.Checked = Properties.Settings.Default.OcrGuessSpecies;
InitializeOcrLabelSets();

// initialize speech recognition if enabled
InitializeSpeechRecognition();
Expand Down Expand Up @@ -446,8 +451,6 @@ private void Form1_Load(object sender, EventArgs e)
SetupExportFileWatcher();

timerList1.SetTimerPresets(Properties.Settings.Default.TimerPresets);

_timerGlobal.Start();
}

/// <summary>
Expand Down Expand Up @@ -2721,6 +2724,12 @@ private void CreateIncubationTimer(Creature mother, Creature father, TimeSpan in
_libraryNeedsUpdate = true; // because mating-cooldown of mother was set
}

private void EnableGlobalTimerIfNeeded()
{
_timerGlobal.Enabled = timerList1.TimerIsNeeded
|| raisingControl1.TimerIsNeeded;
}

private void TimerGlobal_Tick(object sender, EventArgs e)
{
timerList1.Tick();
Expand Down
34 changes: 34 additions & 0 deletions ARKBreedingStats/Form1.extractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Threading;
using System.Windows.Forms;
using ARKBreedingStats.utils;
using ARKBreedingStats.ocr;

namespace ARKBreedingStats
{
Expand Down Expand Up @@ -1150,5 +1151,38 @@ private void LbBlueprintPath_Click(object sender, EventArgs e)
&& !string.IsNullOrEmpty(bp))
Clipboard.SetText(bp);
}

#region OCR label sets

private void InitializeOcrLabelSets()
{
TsCbbLabelSets.Items.Clear();
var labelSetNames = ArkOcr.Ocr.ocrConfig?.LabelRectangles?.Keys.ToArray();
var displayControl = (labelSetNames?.Length ?? 0) > 1;

TsCbbLabelSets.Visible = displayControl;
TsLbLabelSet.Visible = displayControl;
TsSpOcrLabel.Visible = displayControl;

if (!displayControl)
return;

TsCbbLabelSets.Items.AddRange(labelSetNames);
TsCbbLabelSets.SelectedItem = ArkOcr.Ocr.ocrConfig.SelectedLabelSetName;
}

private void SetCurrentOcrLabelSet()
{
TsCbbLabelSets.SelectedItem = ArkOcr.Ocr.ocrConfig.SelectedLabelSetName;
}

private void TsCbbLabelSets_SelectedIndexChanged(object sender, EventArgs e)
{
if (ArkOcr.Ocr.ocrConfig == null) return;
ArkOcr.Ocr.ocrConfig.SetLabelSet(((ToolStripComboBox)sender).SelectedItem.ToString());
ocrControl1.SetOcrLabelSetToCurrent();
}

#endregion
}
}
98 changes: 76 additions & 22 deletions ARKBreedingStats/Form1.importSave.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ARKBreedingStats.uiControls;
using ARKBreedingStats.utils;

namespace ARKBreedingStats
Expand Down Expand Up @@ -50,18 +49,32 @@ private async Task<string> RunSavegameImport(ATImportFileLocation atImportFileLo
workingCopyFolderPath = Path.GetTempPath();
}

var fileLocation = atImportFileLocation.FileLocation;
string uriFileRegex = null;

if (Uri.TryCreate(atImportFileLocation.FileLocation, UriKind.Absolute, out var uri)
var indexLastSlash = fileLocation.LastIndexOf('/');
if (indexLastSlash > 0)
{
var lastUriSegment = fileLocation.Split('/').Last();
if (lastUriSegment.Contains("*") || lastUriSegment.Contains("(?<"))
{
fileLocation = fileLocation.Substring(0, indexLastSlash);
uriFileRegex = lastUriSegment;
}
}

if (Uri.TryCreate(fileLocation, UriKind.Absolute, out var uri)
&& uri.Scheme != "file")
{
switch (uri.Scheme)
{
case "ftp":
workingCopyFilePath = await CopyFtpFileAsync(uri, atImportFileLocation.ConvenientName,
string errorMessage;
(workingCopyFilePath, errorMessage) = await CopyFtpFileAsync(uri, uriFileRegex, atImportFileLocation.ConvenientName,
workingCopyFolderPath);
if (workingCopyFilePath == null)
if (errorMessage != null)
// the user didn't enter credentials
return "no credentials";
return errorMessage;
break;
default:
throw new Exception($"Unsupported uri scheme: {uri.Scheme}");
Expand Down Expand Up @@ -131,7 +144,7 @@ await ImportSavegame.ImportCollectionFromSavegame(_creatureCollection, workingCo
return null; // no error
}

private async Task<string> CopyFtpFileAsync(Uri ftpUri, string serverName, string workingCopyFolder)
private async Task<(string filePath, string errorMessage)> CopyFtpFileAsync(Uri ftpUri, string fileRegex, string serverName, string workingCopyFolder)
{
var credentialsByServerName = LoadSavedCredentials();
credentialsByServerName.TryGetValue(serverName, out var credentials);
Expand All @@ -150,7 +163,7 @@ private async Task<string> CopyFtpFileAsync(Uri ftpUri, string serverName, strin
{
if (dialog.ShowDialog(this) == DialogResult.Cancel)
{
return null;
return (null, "no credentials given, aborted by user");
}

credentials = dialog.Credentials;
Expand All @@ -164,9 +177,13 @@ private async Task<string> CopyFtpFileAsync(Uri ftpUri, string serverName, strin
}
}
var client = new FtpClient(ftpUri.Host, ftpUri.Port, credentials.Username, credentials.Password);
string ftpPath = null;

try
{
if (progressDialog.IsDisposed)
return (null, "aborted by user");

progressDialog.StatusText = $"Authenticating on server {serverName}";
if (!progressDialog.Visible)
progressDialog.Show(this);
Expand All @@ -181,14 +198,15 @@ private async Task<string> CopyFtpFileAsync(Uri ftpUri, string serverName, strin
progressDialog.StatusText = "Finding most recent file";
await Task.Yield();

var ftpPath = ftpUri.AbsolutePath;
var lastSegment = ftpUri.Segments.Last();
if (lastSegment.Contains("*"))
ftpPath = ftpUri.AbsolutePath;

if (fileRegex != null)
{
var mostRecentlyModifiedMatch = await GetLastModifiedFileAsync(client, ftpUri, cancellationTokenSource.Token);
var mostRecentlyModifiedMatch =
await GetLastModifiedFileAsync(client, ftpUri, fileRegex, cancellationTokenSource.Token);
if (mostRecentlyModifiedMatch == null)
{
throw new Exception($"No file found matching pattern '{lastSegment}'");
throw new Exception($"No file found matching pattern '{fileRegex}'");
}

ftpPath = mostRecentlyModifiedMatch.FullName;
Expand All @@ -212,7 +230,7 @@ private async Task<string> CopyFtpFileAsync(Uri ftpUri, string serverName, strin
filePath = await DecompressGZippedFileAsync(filePath, cancellationTokenSource.Token);
}

return filePath;
return (filePath, null);
}
catch (FtpAuthenticationException ex)
{
Expand All @@ -224,16 +242,18 @@ private async Task<string> CopyFtpFileAsync(Uri ftpUri, string serverName, strin
catch (OperationCanceledException)
{
client.Dispose();
return null;
return (null, "aborted by user");
}
catch (Exception ex)
{
var errorMessage = $"Unexpected error while downloading file\n{ftpPath}:\n{ex.Message}{(string.IsNullOrEmpty(ex.InnerException?.Message) ? null : "\n\nInner Exception:\n" + ex.InnerException?.Message)}";
if (progressDialog.IsDisposed)
{
client.Dispose();
return null;
return (null, errorMessage);
}
progressDialog.StatusText = $"Unexpected error: {ex.Message}";
progressDialog.StatusText = errorMessage + "\n\nTrying again in some seconds.";
await Task.Delay(3000);
}
finally
{
Expand Down Expand Up @@ -282,17 +302,51 @@ private async Task<string> DecompressGZippedFileAsync(string filePath, Cancellat
return newFileName;
}

public async Task<FtpListItem> GetLastModifiedFileAsync(FtpClient client, Uri ftpUri, CancellationToken cancellationToken)
public async Task<FtpListItem> GetLastModifiedFileAsync(FtpClient client, Uri ftpUri, string fileRegex, CancellationToken cancellationToken)
{
var folderUri = new Uri(ftpUri, ".");
var listItems = await client.GetListingAsync(folderUri.AbsolutePath, cancellationToken);

// Turn the wildcard into a regex pattern "super*.foo" -> "^super.*?\.foo$"
var nameRegex = new Regex("^" + Regex.Escape(ftpUri.Segments.Last()).Replace(@"\*", ".*?") + "$");
Regex fileNameRegex;
if (!fileRegex.Contains("(?<"))
{
// assume only simple wildcard
// Turn the wildcard into a regex pattern "super*.foo" -> "^super.*?\.foo$"
fileNameRegex = new Regex("^" + Regex.Escape(fileRegex).Replace(@"\*", ".*?") + "$");

return listItems
.OrderByDescending(x => x.Modified)
.FirstOrDefault(x => fileNameRegex.IsMatch(x.Name));
}

fileNameRegex = new Regex(fileRegex);

// order by named groups descending
var listWithMatches = listItems.Select(f => (ftpFile: f, match: fileNameRegex.Match(f.Name))).Where(f => f.Item2.Success).ToArray();

switch (listWithMatches.Length)
{
case 0: return null;
case 1: return listWithMatches[0].ftpFile;
}

var regexGroupNames = fileNameRegex.GetGroupNames().Where(n => n != "0").OrderBy(n => n).ToArray();
if (regexGroupNames.Length == 0)
return listWithMatches.First().ftpFile;

var orderedListWithMatches =
listWithMatches.OrderByDescending(f => f.match.Groups[regexGroupNames[0]].Value);

for (int g = 1; g < regexGroupNames.Length; g++)
{
var groupName = regexGroupNames[g]; // closure
orderedListWithMatches =
orderedListWithMatches.ThenByDescending(f => f.match.Groups[groupName].Value);
}

var orderedList = orderedListWithMatches.ToArray();

return listItems
.OrderByDescending(x => x.Modified)
.FirstOrDefault(x => nameRegex.IsMatch(x.Name));
return orderedList.First().ftpFile;
}

/// <summary>
Expand Down
24 changes: 13 additions & 11 deletions ARKBreedingStats/Form1.library.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Text.RegularExpressions;
using ARKBreedingStats.library;
using ARKBreedingStats.settings;
using System.Runtime.ConstrainedExecution;

namespace ARKBreedingStats
{
Expand Down Expand Up @@ -1311,30 +1312,31 @@ private void FilterLib(bool selectFirstIfNothingIsSelected = false)
var statFilterRegex = new Regex(@"(\w{2}) ?(<|>|==) ?(\d+)");

// color filter
var colorFilter = new Dictionary<int, int[]>();
var colorFilterRegex = new Regex(@"c([0-5]): ?([\d ]+)");
var colorFilterOr = new Dictionary<int[], int[]>(); // includes creatures that have in one of the regions one of the colors
var colorFilterRegexOr = new Regex(@"c([0-5 ]+): ?([\d ]+)");

// mutation filter
var mutationFilterEqualTo = -1;
var mutationFilterGreaterThan = -1;
var mutationFilterLessThan = -1;

var removeFilterIndex = new List<int>();
var removeFilterIndex = new List<int>(); // remove all filter entries that are added to specific filter properties
// start at the end, so the removed filter indices are also removed from the end
for (var i = filterStrings.Count - 1; i >= 0; i--)
{
var f = filterStrings[i];

// color region filter
var m = colorFilterRegex.Match(f);
var m = colorFilterRegexOr.Match(f);
if (m.Success)
{
var colorRegion = int.Parse(m.Groups[1].Value);
if (colorFilter.ContainsKey(colorRegion)) continue;

var colorIds = m.Groups[2].Value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(cId => int.Parse(cId)).Distinct().ToArray();
var colorIds = m.Groups[2].Value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse).Distinct().ToArray();
if (!colorIds.Any()) continue;

colorFilter[colorRegion] = colorIds;
var colorRegions = m.Groups[1].Value.Where(r => r != ' ').Select(r => int.Parse(r.ToString())).ToArray();

colorFilterOr[colorRegions] = colorIds;
removeFilterIndex.Add(i);
continue;
}
Expand Down Expand Up @@ -1382,7 +1384,7 @@ private void FilterLib(bool selectFirstIfNothingIsSelected = false)
if (!statGreaterThan.Any()) statGreaterThan = null;
if (!statLessThan.Any()) statLessThan = null;
if (!statEqualTo.Any()) statEqualTo = null;
if (!colorFilter.Any()) colorFilter = null;
if (!colorFilterOr.Any()) colorFilterOr = null;
foreach (var i in removeFilterIndex)
filterStrings.RemoveAt(i);

Expand All @@ -1399,7 +1401,7 @@ private void FilterLib(bool selectFirstIfNothingIsSelected = false)
&& (statGreaterThan?.All(si => c.levelsWild[si.Key] > si.Value) ?? true)
&& (statLessThan?.All(si => c.levelsWild[si.Key] < si.Value) ?? true)
&& (statEqualTo?.All(si => c.levelsWild[si.Key] == si.Value) ?? true)
&& (colorFilter?.All(cr => cr.Value.Contains(c.colors[cr.Key])) ?? true)
&& (colorFilterOr?.All(colorRegions => colorRegions.Key.Any(colorRegion => colorRegions.Value.Contains(c.colors[colorRegion]))) ?? true)
&& (mutationFilterGreaterThan == -1 || mutationFilterGreaterThan < c.Mutations)
&& (mutationFilterLessThan == -1 || mutationFilterLessThan > c.Mutations)
&& (mutationFilterEqualTo == -1 || mutationFilterEqualTo == c.Mutations)
Expand Down
Loading

0 comments on commit d7e43e3

Please sign in to comment.