Jump to content
Sign in to follow this  
demonized

Array usage question

Recommended Posts

Problem resolved, answer on page 2 of thread, BIG thank you shk, GDICommand and UNN

quick jump to solution post: http://forums.bistudio.com/showpost.php?p=1813136&postcount=12

I was trying to do locating on different elements in an array.

So i started experimenting and this is what ive come up with, but cant get it to work, im a novice scripter learning on the fly.

I cant see how this is not working...:confused: Probably a simple thing right??

How can i find the object in array after a named one?

Ill try and show instead what i want to achieve:

i call a script with _nul = ["someshit","crap","min",59] execVM "thescript.sqf"

_ALLParams = [];
for [{_i=0},{_i<count _this},{_i=_i+1}] do {_e=_this select _i; if (typeName _e=="STRING") then {_e=toUpper(_e)};_ALLParams set [_i,_e]};

_stillLooking = false;
_getArrNR = 0;
_minNR = 0;

if ("MIN" in _ALLParams) then {
_stillLooking = true;
while {_stillLooking} do {
	if (_this select _getArrNR == "MIN") then {
		_getArrNR = _getArrNR + 1;
		_minNR = _this select _getArrNR;
		hint format["%1",_minNR];  // for debug.
		_stillLooking = false;
	} else {
		_getArrNR = _getArrNR + 1;
		sleep 0.1;
	};
};
sleep 5;  // for debug.
hint "MIN VALUE FOUND";  // for debug.
sleep 5;  // for debug.
hint format["%1",_minNR];  // for debug.
};

Asume that i dont have _this select 0,1,2,3 for the array, i only use this select 0 for first needed in array, rest can be entered in any order in the array, well, thats what i want anyhow, much like the upsmon script uses if anyone is familiar with that.

"min" and ,59 belongs together to give me info to my script.

How can i locate what number _this select ? "min" is??

And how can i locate variable after "min"? in this case 59.

I do find "min" in array(tested with hint) but recives Error Generic error in expression for this line in the above while loop

if ((_this select _getArrNR) == "MIN") then {

Any help will be much appreciated.

Edited by Demonized
problem have been resolved

Share this post


Link to post
Share on other sites

_getArrNR = _getArrNR + 1;
_minNR = _this select [b]_getArr[/b];

Is that supposed to be _getArrNR?

Edit: Nevermind, there actual was another }, just horrible code formating hiding it. Saving in the number of lines you make is not helping anyone :G

---------- Post added at 10:34 PM ---------- Previous post was at 10:14 PM ----------

if ((_this select _getArrNR) == "MIN") then {  

You are selecting from _this instead of _ALLParams?

Anyway, how about something like this (didnt test it though)?

private ["_ALLParams","_minNR","_i","_e"];
_ALLParams = [];

// Change all strings to uppercase
for [{_i=0},{_i<count _this},{_i=_i+1}] do {
 _e = _this select _i;
 if (typeName _e == "STRING") then {
   _e = toUpper(_e);
 };
 _ALLParams set [_i,_e];
};

// Find minimum value
_minNR = 0;
if ("MIN" in _ALLParams) then {
 _e = -1;
 {
   _e = _e + 1;
   if (_x == "MIN") exitwith {_minNR = _ALLParams select (_e + 1)};
 } foreach _ALLParams;
};

Edited by Shuko

Share this post


Link to post
Share on other sites

im not really sure what youre trying to do here. from what it sounds like, youre trying to iterate over an array, find an object, and determine what index of the array the object is located at. what is the object your searching for? im assuming its a string since "MIN" is one of the objects youre looking for

im terrible with this code, and i normally get it wrong (im used to writing in a very...very different syntax) but here is what I think youre trying to do:

indexNumber = -1;
for[{_i = 0}, {_i < count arrayYoureIteratingOver}, {_i++}]do{
   if(arrayYoureIteratingOver select _i == objectYoureCheckingAgainst){
       indexNumber = _i;
       break;
   }
};

im not sure if this game uses the "++" operator, but if it doesnt, replace "i++" with "_i = _i + 1"

as for the rest of it, id have to test that, because theres a few things that I dont know if arma ii can do (like comparing objects, or what the syntax is for break in loops)

---------- Post added at 15:49 ---------- Previous post was at 15:40 ----------

while im looking at your code, i dont see where youre setting _getArr. but furthermore, you have a much bigger problem, youre not doing any bounds checking while you iterate through your while loop. im not sure how arma ii handles ArrayOutOfBoundsExceptions, but it could be the reason for your "Generic Error" (terrible exception feedback if your listening developers...i dont know what joke of a language they modeled this after)

anyway, that while loop should be a for loop, youre doing some things that traditionally should be done in a for loop

Share this post


Link to post
Share on other sites

thanks for the replys guys. sorry if i wasnt clear in my first post.

What i wanted was if i had put "min" follwed by ,number_of_any_kind.

Like this ["min",59] execVM.....

I wanted to do a check if "min" was present in array, then i would get its position and get the value of the next param in array after "min", wich in this case was 59

I think you guys have given me the solution anyway so im testing now.

Btw: what is _i and _e?? is it same as _x used in foreach commands?

Share this post


Link to post
Share on other sites
Btw: what is _i and _e?? is it same as _x used in foreach commands?

No. They are just temporary variables (you can use any variable name), while _x is a special variable.

Share this post


Link to post
Share on other sites

thanks for the replys guys. sorry if i wasnt clear in my first post.

What i wanted was if i had put "min" follwed by ,number_of_any_kind.

This was a typo mistake when i changed the names to make it as clear as possible for anyone looking at it. :hammer:

Fixed 1st post.

_minNR = _this select _getArr;

Btw: what is _i and _e?? is it same as _x used in foreach commands?

Ok tnx SHK.

@GDICommand

by bound i assume you mean if i select a number value wich isnt there in array?

example: myarr = [1,2,3] ---- and if i select myarr select 3 (wich isnt in array its out of bounds right?

I am aware of this so i used a local var named _stillLooking and declared it true before the while loop.

while {_stillLooking} do {

And when i found what number to select my target with, like seen here:

if (_this select _getArrNR == "MIN") then {

I declared _stillLooking for false and loop would end without going out of bounds.

At least thats how i have made similar things work...

@shk

You are selecting from _this instead of _ALLParams?

i asumed the array _ALLParams to be exact copy or replica of _this array, thats why i did, came up same error with using _ALLParams instead of _this there when i tried before posting 1st time.

Edit: tried your version shk, same generic error message.

here is rpt file:

Error in expression <) then {
_e = -1;
{
_e = _e + 1;
if (_x == "MIN") exitwith {_minNR = _ALLParams >
 Error position: <== "MIN") exitwith {_minNR = _ALLParams >
 Error Generic error in expression

Edit2: not working with any suggestion, and while researching more into for i found this

http://community.bistudio.com/wiki/for_var

So checking now if i can set letters to lover or just not set them to any and just use lower in execVM line.

Edit3: @GDICommand

i didnt find any break command but maybe this does same?

http://community.bistudio.com/wiki/lineBreak

Edited by Demonized

Share this post


Link to post
Share on other sites

Silly me. Comparing non string params as well.

private ["_ALLParams","_minNR","_i","_e"];
_ALLParams = [];

// Change all strings to uppercase
for [{_i=0},{_i<count _this},{_i=_i+1}] do {
 _e = _this select _i;
 if (typeName _e == "STRING") then {
   _e = toUpper(_e);
 };
 _ALLParams set [_i,_e];
};

// Find minimum value
_minNR = 0;
if ("MIN" in _ALLParams) then {
 _e = -1;
 {
   _e = _e + 1;
     if ([b]str [/b]_x == "MIN") exitwith {_minNR = _ALLParams select (_e + 1)};
 } foreach _ALLParams;
};

---------- Post added at 11:52 PM ---------- Previous post was at 11:48 PM ----------

Hmm, maybe you dont need to uppercase them before. How about just:

_minNR = 0;
_e = -1;
{
 _e = _e + 1;
   if (toupper (str _x) == "MIN") exitwith {_minNR = _this select (_e + 1)};
} foreach _this;

Share this post


Link to post
Share on other sites

Ok guys i wont stress you any more, my script can fully work without this, but having this would be nice nonthe less.

tried various commands, with shk version i managed to get a hint with 0 even though my wanted target was 5th line in array, also got generic error every time.

with GDICommand version i got hint with 2, or 3 but still same generic error.

This is whats done in UPSMON wich i want my self:

in upsmon.sqf:

// convert argument list to uppercase
_UCthis = [];
for [{_i=0},{_i<count _this},{_i=_i+1}] do {_e=_this select _i; if (typeName _e=="STRING") then {_e=toUpper(_e)};_UCthis set [_i,_e]};

further down in upsmon.sqf there is:

_ambushwait = ["AMBUSH:",_ambushwait,_UCthis] call KRON_UPSgetArg;

ambush is entered same way as i wanted my min, followed by a number. Example =

["someRandom","someRandom","someRandom","ambush",numberToWaitForAmbush]

Now i look up KRON_UPSgetArg wich is located in upsmon_init.sqf wich is run from initfile, also at missionstart:

// Misc
KRON_UPSgetArg = {private["_cmd","_arg","_list","_a","_v"]; _cmd=_this select 0; _arg=_this select 1; _list=_this select 2; _a=-1; {_a=_a+1; _v=format["%1",_list select _a]; if (_v==_cmd) then {_arg=(_list select _a+1)}} foreach _list; _arg};
KRON_UPSsetArg = {private["_cmd","_arg","_list","_a","_v"]; 
	_cmd=_this select 0; 
	_arg=_this select 1; 
	_list=_this select 2; 
	_a=-1; 
	{	
		_a=_a+1; 
		_v=format["%1",_list select _a]; 
		if (_v==_cmd) then {
			_a=_a+1; 
			_list set [_a,_arg];
			};
		} foreach _list; 
	_list};
KRON_deleteDead = {private["_u","_s"];_u=_this select 0; _s= _this select 1; _u removeAllEventHandlers "killed"; sleep _s; deletevehicle _u};


Not sure if thats all related but here it is anyways.. i could post entire upsmon script and upsmon_init, but not sure if im allowed since its Monsadas script.

Edit: noticed "ambush:" ----- a colon was in there. :

Maybe thats what is missing. but this is atm beyond my scripting skills, but if any of you like to crack it for me to put in a same script as i want it used or do similar as Upsmon.sqf and upsmon_init.sqf then id be very happy.

EDit, didnt see your last post shk , testing now :)

---------- Post added at 11:32 PM ---------- Previous post was at 11:22 PM ----------

@shk

deffinetly on right path;

no errors but wrong number, i got 0 but i should get last, maybe when added to array from _this its reversed.. retesting.

Edit; tried ignoring the whole add to and set uppercase and just vent with check switching out _ALLParams with _this but same result, no errors but still get 0 when i should get 5.

only active was the private lines at top and rest below // Find minimum value

---------- Post added at 11:45 PM ---------- Previous post was at 11:32 PM ----------

_minNR = 0;
_e = -1;
{
 _e = _e + 1;
   if (toupper (str _x) == "MIN") exitwith {_minNR1 = _this select (_e + 1)}; hint format["%1",_minNR1];
} foreach _this;

i recieved 0 everytime and no errors. figured i try switching name of hint so i added a 1 in hint and _minNR1 and now i get hint any...

Edited by Demonized

Share this post


Link to post
Share on other sites
No. They are just temporary variables (you can use any variable name), while _x is a special variable.

how is _x is a special variable? variables are just that, they are variables...im not familiar with this language a hundred percent, but ive used it in multiple contexts, and there doesn't appear to be anything preventing any data type from going into it.

@GDICommand

by bound i assume you mean if i select a number value wich isnt there in array?

example: myarr = [1,2,3] ---- and if i select myarr select 3 (wich isnt in array its out of bounds right?

I am aware of this so i used a local var named _stillLooking and declared it true before the while loop.

while {_stillLooking} do {

And when i found what number to select my target with, like seen here:

if (_this select _getArrNR == "MIN") then {

I declared _stillLooking for false and loop would end without going out of bounds.

At least thats how i have made similar things work...

unfortunately it doesnt work that way. the way i imagine things when i write code (and how you should always do it) is, you have to ask yourself "how could i execute this code and break it?"

so right off the bat, something instantly comes to my mind. I can envision a scenario where that array doesn't have what youre looking for. in that case, you will continue to iterate until you reach one index past the last index of the array and then the loop will break:

so say youre looking for a string inside of an array that contains the value "Neon-Pink-Chopper"

now, lets see an array that doesnt contain that string:

[index 1 data: "ketchup"][index 2 data: "mustard"][index 3 data: clown shoes"]

it will skip past the first part of the if statement in your while loop, and move to your else, which tells it to increment a number which tells the program to seek to the address which contains the next value in the array (for simplicity's sake). clearly it will continue to do that until now youre _getArrNR integer equals 3 because there is nothing stopping it from reaching three, and trying to retrieve the data at the "fourth" index.

what happens when you select index four? (arrayName select 3)

ArrayOutOfBoundsException (or whatever arma calls it)

the reason why this causes problems is because normally, you have to allocate memory to access it, which im assuming happens in this language by just assigning stuff to it at creation time (im not aware of a way in this language to increase the size of an array, which there isnt a way in any language (theres kind of hacky ways to do it in some, but ill leave that one go) so it would make sense that you can't here as well...EDIT: actually there kind of is a way, but it technically isn't extending the array...but i dont want to get too far into low level)...anyways im looking at what im writing and im kind of getting off topic...

anyway, the point is, youre not using the count command. which is a dead give away that your while loop has no idea where the end of the loop is (and it needs to know). and if armaii error reporting is half as good as i get the picture it is, the general error could well be that youre trying to access a memory address that you dont have control over.

Edit3: @GDICommand

i didnt find any break command but maybe this does same?

http://community.bistudio.com/wiki/lineBreak

no. a "break" statement is basically a command that tells youre program to break out of the loop. so as soon as it receives it, it tells it to jump to just after the closing bracket of the loop and continue to execute. this could probably tell you better than i could:

http://msdn.microsoft.com/en-us/library/wt88dxx6%28v=vs.80%29.aspx

so in the example in the link above, the loop will continue until the user enters c, and presses enter. when the if statement

if(c == 'Q') evaluates to true, then the break statement is reached, which tells it to jump to directly after the closing bracket in the loop

---------- Post added at 22:10 ---------- Previous post was at 21:55 ----------

@shk

deffinetly on right path;

no errors but wrong number, i got 0 but i should get last, maybe when added to array from _this its reversed.. retesting.

Edit; tried ignoring the whole add to and set uppercase and just vent with check switching out _ALLParams with _this but same result, no errors but still get 0 when i should get 5.

only active was the private lines at top and rest below // Find minimum value

---------- Post added at 11:45 PM ---------- Previous post was at 11:32 PM ----------

_minNR = 0;
_e = -1;
{
 _e = _e + 1;
   if (toupper (str _x) == "MIN") exitwith {_minNR1 = _this select (_e + 1)}; hint format["%1",_minNR1];
} foreach _this;

i recieved 0 everytime and no errors. figured i try switching name of hint so i added a 1 in hint and _minNR1 and now i get hint any...

i dont know what youre whole code looks like, but youre not printing to screen when you receive the correct index. youre saying (in pseudo code):

_minNR = 0;
_e = -1;
{
 increment _e before the loop begins to execute;

 if (the uppercase value of _x equals "MIN")  then exit with, setting 
      minNR1 = the index above _e (which was "MIN")};

 but if the if statement doesnt evaluate to true (if it doesnt equal "MIN"),
 then print to the screen the value of _minNR1

}foreach _this;

basically what that means, is that youre code wont print a value to the screen if it finds what its looking for. so all youre gonna see is 0.

try this, always put a bracket on a line by itself, its a coding convention most people follow, makes your code easier to read. the way it is now, its not surprising that you didnt catch that, but if you partition the code properly, then you will see what i saw when i looked at it:

_minNR = 0;
_e = -1;
{
 _e = _e + 1;
   if (toupper (str _x) == "MIN") 
   exitwith {
       _minNR1 = _this select (_e + 1)
   };
   hint format["%1",_minNR1];
} foreach _this;  

EDIT: BTW, I'm pretty sure if(condition) exitwith{ }; is kind of like the break statement i wanted. im pretty sure if you just left the squiggly brackets empty, that would effectively be the break statement. otherwise, it's kind of like the return keyword that languages use in functions or methods, it executes a piece of code, and then it returns a value with it. in your case, it returns an integer that references the index number that you want

EDIT2: forgot to tell you. if you get general errors like that, then its a good idea to start dumping everything to the screen. in arma, its kind of a pain, because dumping one thing to the screen will write over whatever was there before, so you have to put timers in, but either way...the only way to figure out why something is breaking, is to dump information to the screen. for example, if you want to make sure a while loop is executing properly over an iteration, put a hint statement at the very start, and very end of the loop...this tells you that the loop executed from start to finish successfully. im gonna use a for loop, just so i can see what iteration im on and dump it to the screen for this example:

hint "just before for loop";
for[{_i = 0}, {_i < array count}, {_i = _i + 1}] do{
   hint format ["for loop start, execution: %1", _i];
   //do some actions here
   if(someBooleanCondition){
       hint format ["if statement start, execution: %1", _i];
       //do some actions here
       hint "if statement end";
   };
   hint "end for loop";
}
hint "just after for loop";

obviously you will have to wait just after those messages, but you get the idea. now i can see just before the loop starts, make sure the variables and conditions are executed properly by seeing that the first iteration started. i can see what iteration im on, i can see when the if statement starts and ends, so if it enters the if statement, i know the statement was evaluated to true. i can see where the for loop ends, which important so that way you can tell if it got past your internal statements inside of the loop. and i can also see when my program exited the loop.

i always tell people, when writing a code, always use i/o to your advantage, its the most useful way to figure out what youre program is doing...other than a program which steps through your code line by line...thats irrelevant though because without even searching for it, i can say with about 99 percent certainty that arma doesnt support it, and further more, with another 99 percent certainty, that nobody has taken the time to develop it for this game

Edited by GDICommand

Share this post


Link to post
Share on other sites

If you're running Operation Arrow Head, you can now use the following:

_minNR=-1;

{if (_x=="MIN") exitWith {_minNR=_forEachIndex}} forEach _this;

if (_minNR!=-1) then
{
hint format ["String at index %1",_minNR];
}
else
{
hint "Not found";
};

If your running Arma2 then this is another way:

_minNR=0;

{if (_x=="MIN") exitWith {} ; _minNR=minNR+1} forEach _this;

if (_minNR<(count _this)) then
{
hint format ["String at index %1",_minNR];
}
else
{
hint "Not found";
};

When comparing strings with == the engine does not take upper and lower case text into account. If you look for a string within an array using the in or commands, it will take upper and lower case into account.

Because it has a value automatically assigned when running in a forEach loop. A similar thing applies to _this and this. Both can be populated automatically by the engine, so best to avoid using them for anything other than what they were intended for.

Edited by UNN

Share this post


Link to post
Share on other sites

Because it has a value automatically assigned when running in a forEach loop. A similar thing applies to _this and this. Both can be populated automatically by the engine, so best to avoid using them for anything other than what they were intended for.

oo...thats a big one...didn't realize that...i guess i just never defined x before a loop or something before...at least now i know to avoid it...thanks lol

Share this post


Link to post
Share on other sites

Well i got it working with a modification of what UNN posted.

I suspect the other examples ive recieved by shk and GDICommand will work with similar adjustment, not yet tested that.

I tried both arma2 and oa version of UNN´s posted scripts, both worked with same adjustment, but i do own complete arma2, OA, all dlcs.

Objective is to find the position in the array that "min" is in, and then add +1 to that to get the one after "min".

i used in a radio trigger this:

_null = ["ohoy","milkshake","niceT",4572,"min",57] execVM "testScript.sqf";

i also tested with thiss to confirm it was not just luck:

_null = ["ohoy","milkshake","min",4572,"niceT",57] execVM "testScript.sqf";

1st trigger i wanted hint to display number 5(wich is location of value after "min") - target is now 57

2nd trigger i wanted number 3(wich is location of value after "min") - target is now 4572

UNN posted these scripts:

Operation Arrowhead version:

_minNR=-1;

{if (_x=="MIN") exitWith {_minNR=_forEachIndex}} forEach _this;

if (_minNR!=-1) then
{
hint format ["String at index %1",_minNR];
}
else
{
hint "Not found";
};

Arma2 version wich had a typo error wich ive fixed:

_minNR=0;
//  typo below corrected from minNR to _minNR
{if (_x=="MIN") exitWith {} ; _minNR=_minNR+1} forEach _this;

if (_minNR<(count _this)) then
{
hint format ["String at index %1",_minNR];
}
else
{
hint "Not found";
};

Now these didnt work, same generic error as with all other previous script attempts.

Then i got to thinking of what shk said about comparing non string to string.

so i modified scripts like this:

Operation Arrowhead version:

_minNR=-1;

{if (str(_x)==str("MIN")) exitWith {_minNR=_forEachIndex}} forEach _this;

if (_minNR!=-1) then
{
hint format ["String at index %1",(_minNR+1)];
}
else
{
hint "Not found";
};

Arma2 version:

_minNR=0;

{if (str(_x)==str("MIN")) exitWith {} ; _minNR=_minNR+1} forEach _this;

if (_minNR<(count _this)) then
{
hint format ["String at index %1",(_minNR+1)];
}
else
{
hint "Not found";
};

At top i modified _x and "MIN" to str(_x) and str("MIN") that gave me a message saying String at index 4 in 1st trigger and String at index 2 in 2nd trigger, now this is the actual position of "min" and not the next one.

changing _minNR before foreach check to 0 or 1 didnt have any effects, got same number in hint, unknown why, maybe outside number not taken into inside if... anyhow..

So i changed hint format ["String at index %1",_minNR]; to hint format ["String at index %1",(_minNR+1)];

And now in 1st trigger i want 5 as hint and i get String at index 5

in 2nd trigger i want 3 as a hint and i get String at index 3

Its all working :yay:

At least the correct hint is working, now to actually implement it in a script with selection based on this, ill work up a script now, and post it here, tho i suspect it will work as intended anyway, but just checking.

@GDICommand

unfortunately it doesnt work that way. the way i imagine things when i write code (and how you should always do it) is, you have to ask yourself "how could i execute this code and break it?"

so right off the bat, something instantly comes to my mind. I can envision a scenario where that array doesn't have what youre looking for. in that case, you will continue to iterate until you reach one index past the last index of the array and then the loop will break:

youre right, ofcourse i would have a if ("min" in _this) then {run the while loop, so then while loop would exit correctly because it will never run if min not there. also asuming if min was entered in an array it would always be followed by a number like this ["min",567], at least thats how i think about it, have used before with other while loops sucessfully, maybe ive only been lucky :j: i dunno.

A big thank you to all for great response, and problem solving. :bounce3:

---------- Post added at 07:25 PM ---------- Previous post was at 07:21 PM ----------

_minNR=-1;

{if (str(_x)==str("MIN")) exitWith {_minNR=_forEachIndex}} forEach _this;

if (_minNR!=-1) then
{
hint format ["String at index %1",(_minNR+1)];
_minNR = _minNR + 1;
}
else
{
hint "Not found";
};
sleep 5;
//hint format ["%1",_minNR];
_MYdisplay = _this select _minNR;
hint format ["%1",_MYdisplay];

Actual implement in script, hint at end of script displays now the correct value wich can be used further down in script. :yay:

Edited by Demonized

Share this post


Link to post
Share on other sites

@GDICommand

youre right, ofcourse i would have a if ("min" in _this) then {run the while loop, so then while loop would exit correctly because it will never run if min not there. also asuming if min was entered in an array it would always be followed by a number like this ["min",567], at least thats how i think about it, have used before with other while loops sucessfully, maybe ive only been lucky :j: i dunno.

you are right, that would work. but you have to think about it like this: youre mission is executing on a time-table. the "in" command basically iterates over the array in a linear fashion (unless there is another data structure they are storing arrays in...but probably not). what that means is that the in command will have to iterate over the array one index at a time, which means that the complexity of the search is worst case scenario, which is it will have to iterate n times, where n is the number of indexes in the array. however, you arent actually pulling any data from the array on that pass, you are doing a loop yourself if it does find it. so the complexity of that is now 2n + (operations), which in terms of complexity, does go back down to n (don't get hung up on that)

the point im making is that youre code is doing the same exact thing twice. why do it twice when the for loop you made can do it for you? especially if you want things done fast fast fast, then it is a much better idea to only iterate once, especially if your n approaches infinity, and the value you want is the last index (general case), then looping through twice becomes very inefficient. just food for thought for the next time you deal with arrays

Share this post


Link to post
Share on other sites

Youre right, as i said im a very novice scripter, for my scripts it have been more about actually working without errors, than beeing efficient, so my codes are very primitive.

I just begun to get serious into scripts last few months.

Learning alot from you more experienced guys.

Regards

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×