Bit of help from real programmers needed ;) passing constants from bot.config to app?

I’m kind of familiar with programming but semi-noob in C#. I have my moments, but now I’m struggling with probably very simple task :slight_smile:

I did defined for myself Constants.cs which gathers all variables for bot to run eg. which sites to run, which collidables to orbit etc. just for me to have cleaner and readable code.

What I’m wondering is, how to pass those information from bot.config file? eg. to be able to reconfigure bot without building new one.

It looks like I can’t use something like that in Constats, whils before I of course added stuff to Config.cs

namespace Sanderling.ABot.Bot
{
	public class Constants
	{
        public Bot bot;
		public const int TargetCountMax = 4;

		public const string AnomalyGroupName = bot?.ConfigSerialAndStruct.Value?.AnomalyGroupName;

    }
}

I do have updated config.cs like so

namespace Sanderling.ABot.Bot
{
	public class Config
	{
		public string AnomalyGroupName;
		public string AnomalyName;

		public string RetreatBookmark;

		public string[] ModuleActivePermanentSetTitlePattern;

	}
}

because it says “the name bot does not exists in current context”
but if i’ll do it like other classe with get enumerables which can retrieve content from that bot.config variable then I cannot declare it as public static anymore.

So I’m in kinda loop.
Any hint will be really appreciated :slight_smile: Thanks

write anomallygroupname in bot.conf.
configserial take the infos from config.cs
define anomalyfroupname in config.cs ( you have there the pattern)

that is of course part of the issue which I already did … but not what am asking for.
What I’m asking for is how to add those values to the constants as in my example. Cos this is not really working :wink:

I’m not really understand why you dont want use bot.config: you can change this file without recompile main programm.
But anyway in your case you should use readonly keyword. Your class should be static with constructor which take bot as parametr and set public static readonly fields instead of constants. (Sorry for for the carelessness.)
Maybe this will be helpfull and this.

sorry maybe I did not expressed myself correctly, i DO want to use bot.config indeed and I know how to work with most of those things.
Issue is, that I can’t get to work to take data from bot.config and put them as constants in my new class, which will then be used in other parts of the bot.

What is working just fine is to declare constants inside bot in given class. What I really need to help with is, how to pass data from bot.config to constants class.

If I’ll try same approach as with bookmarks, it is not working like in first example.

here is what i want to achieve.:

bot.config
{
“AnomalyGroupType” : “Name”,
“AnomalyTypes” : [“haven”,“sanctum”],
“RetreatBookmark”: “SAFE”
}

Config.cs

namespace Sanderling.ABot.Bot
{
	public class Config
	{
		public string AnomalyGroupName;
		public string[] AnomalyTypes;

		public string RetreatBookmark;

		public string[] ModuleActivePermanentSetTitlePattern;
	}
}

and I’m struggling how to pass those into this:

namespace Sanderling.ABot.Bot
{
	public class Variables
	{
		public Bot bot;

		public const int TargetCountMax = 4;
		public const int TargetingRange = 64000;

		// anomalies select process
		public const string AnomalyGroupName = ???
		public const ???? AnomalyTypes = value from bot.config like "haven|rally" 		
	}
}

Because after that, I simply use this in the code later

		static public bool AnomalySuitableGeneral(Interface.MemoryStruct.IListEntry scanResult) => scanResult?.CellValueFromColumnHeader(Variables.AnomalyGroupName)?.RegexMatchSuccessIgnoreCase(Variables.AnomalyTypes) ?? false;

I’ve tried public static readonly whatever, but it is always keep saying that bot is not initialized.

TL;DR: how to propagate data from bot.config ? because

bot?.ConfigSerialAndStruct.Value?.AnomalyGroupName;

does not work

Are you trying to do it from a scratch or you just rebuilding ABot?
Thats how its implemented in ABot

void BotConfigLoad()
		{
			Exception exception = null;
			string configString = null;
			var configFilePath = AssemblyDirectoryPath.PathToFilesysChild(BotConfigFileName);

			try
			{
				using (var fileStream = new FileStream(configFilePath, FileMode.Open, FileAccess.Read))
					configString = new StreamReader(fileStream).ReadToEnd();
			}
			catch (Exception e)
			{
				exception = e;
			}

			BotConfigLoaded = new PropertyGenTimespanInt64<KeyValuePair<Exception, StringAtPath>>(new KeyValuePair<Exception, StringAtPath>(
				exception,
				new StringAtPath { Path = configFilePath, String = configString }), GetTimeStopwatch());
		}

later its made like

PropertyGenTimespanInt64<KeyValuePair<Exception, StringAtPath>> BotConfigLoaded;

ConfigSerial = BotConfigLoaded?.Value.Value

and

public KeyValuePair<Deserialization, Config> ConfigSerialAndStruct { private set; get; }

ConfigSerialAndStruct = (input?.ConfigSerial?.String).DeserializeIfDifferent(ConfigSerialAndStruct);

In otherwords you need to read it with filestream and then parse on each step if different.

i wanted to use build in features for sure, but as I said → I’m missing something… because simple:

public const string AnomalyGroupName = bot?.ConfigSerialAndStruct.Value?.AnomalyGroupName;

does not work

try it like this

public const string AnomalyGroupName = Bot?.ConfigSerialAndStruct.Value?.AnomalyGroupName;

that gives me “Bot” is a type which is not valid in the given context

if with small bot (and declared like public Bot = bot) it gives me
A field initializer cannot reference the non-static field, method or property “Variables.bot”

So I’m still trying to figure it out, but without much luck.

Why this code is working:

namespace Sanderling.ABot.Bot.Task
{
	public class TestTask : IBotTask
	{
		public Bot Bot;

		public IEnumerable<IBotTask> Component
		{
			get
			{
				var AnomalyGroupName= Bot?.ConfigSerialAndStruct.Value?.AnomalyName;

but when I do:

namespace Sanderling.ABot.Bot
{
	public static class TestClass
	{
		public static Bot Bot = new Bot();
		public static string AnomalyGroupName = Bot?.ConfigSerialAndStruct.Value?.AnomalyName;

It’s getting build without errors, but field is null instead of value from config.

It does look like i can use data from bot.config as variables inside classes, but i can’t use them for definition of public statics which then are used on other places.

I did added it to config.cs

namespace Sanderling.ABot.Bot
{
	public class Config
	{
		public string AnomalyGroupName;

Is there anything else needed what I’m missing?

Sorry for delay. Time for holidays and rest …
I can suggest the following: the values that will be stored in the code - stored in constants, the values that will be taken from the file - stored in readonly variables.
for example Bot.cs:


namespace Sanderling.ABot.Bot
{
	public class Bot
	{
		public KeyValuePair<Deserialization, Config> ConfigSerialAndStruct { private set; get; }
		// new property for storing constants
		public Variables ConfigConstants { private set; get; }

		void MemorizeStepInput(BotStepInput input)
		{
			ConfigSerialAndStruct = (input?.ConfigSerial?.String).DeserializeIfDifferent(ConfigSerialAndStruct);
			// set values for a new property
			ConfigConstants = new Variables(ConfigSerialAndStruct.Value);

			MemoryMeasurementAtTime = input?.FromProcessMemoryMeasurement?.MapValue(measurement => measurement?.Parse());
			MemoryMeasurementAccu.Accumulate(MemoryMeasurementAtTime);
			OverviewMemory.Aggregate(MemoryMeasurementAtTime);
		}

	}
	
	// class to describe the structure of a new property
	public class Variables
	{
		public Variables(Config config)
		{
			if (config == null) return;

			RetreatBookmark = config.RetreatBookmark;
			//AnomalyGroupName = config.AnomalyGroupName;
			//AnomalyTypes = config.AnomalyTypes;
		}

		public const int TargetCountMax = 4;
		public const int TargetingRange = 64000;

		// anomalies select process
		public readonly string RetreatBookmark;

		public readonly string AnomalyGroupName;
		public readonly string AnomalyTypes;
	}

}

now our constants and config propertys are available as

bot.ConfigConstants.TargetCountMax 
bot.ConfigConstants.AnomalyGroupName 

In fact, we reduced only the length of writing and grouped all the constants into one variable.

If we want to use a static class that will contain all the constants + variables from the config file AND will be available throughout the application, we need to write our own reading procedure from the file and place it in the static constructor.

Thank you for your reply.
Good idea, it basically does not matter where it is … but unfortunately I’m getting same error as before when I try to use them outside :

namespace Sanderling.ABot.Bot.Task
{
	public class AnomalyEnter : IBotTask
	{
		public const string NoSuitableAnomalyFoundDiagnosticMessage = "no suitable anomaly found. waiting for anomaly to appear.";

		public Bot bot;

		static public bool AnomalySuitableGeneral(Interface.MemoryStruct.IListEntry scanResult) => scanResult?.CellValueFromColumnHeader(bot?.ConfigConstants.AnomalyGroupName)?.RegexMatchSuccessIgnoreCase(bot?.ConfigConstants.AnomalyTypeNames) ?? false;

"An object reference is required for the non-static field, method, or property ‘AnomalyEnter.bot’ "

:sweat:

Why AnomalySuitableGeneral is static?

1 Like

dunno? its been like that from a-bot source :slight_smile:

update: so i’ve removed static from it and it works like a charm.
You are my hero m8! :slight_smile:

So now, every aspect I want is configurable externaly, so i do not have to recompile exe everytime I want to switch from havens to rallypoints etc.!

Thank you!