Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Hughmoris
Apr 21, 2007
Let's go to the abyss!
I'm a complete beginner with programming and I need a little insight on how to tackle a simple work problem. Ideally I'd like to use AutoIt to tackle this although Ithaqua was kind enough to show me a Powershell solution.

I have a text file, of unknown length, composed of AutoIt code. What I want to do is insert Sleep(xxx) between each line of code. It currently looks like this:
code:
Mouseclick 1
Mouseclick 1
Send("foobar")
Mouseclick 1
Mouseclick2
etc...
I'd like it to look like:
code:
Mouseclick 1
Sleep(500)
Mouseclick 1
Sleep(500)
Send("foobar")
Sleep(500)
Mouseclick 1
Sleep(500)
Mouseclick2
etc....
I've learned how to read in a text file, and loop over its contents line by line. I was thinking I could read in a line, copy it to a new file, then write Sleep(xxx) to new file, then read in next line etc... but I'm getting confused with filehandles and file location etc...

Any ideas?

Adbot
ADBOT LOVES YOU

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Hughmoris posted:

I've learned how to read in a text file, and loop over its contents line by line. I was thinking I could read in a line, copy it to a new file, then write Sleep(xxx) to new file, then read in next line etc... but I'm getting confused with filehandles and file location etc...

Any ideas?

Yeah, that's basically what you would do. Here's a C# solution that you can screw around with: https://dotnetfiddle.net/C9A3Ux. Note that it's on a website that lets you run .NET code, but it won't allow arbitrary file access so I've set it up to run with test data. I've also added some sample code for using it with files.

EDIT: Doh, didn't catch that you wanted to do it in AutoIt.

Bognar fucked around with this message at 22:52 on Jul 28, 2014

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Hughmoris posted:

Any ideas?

AutoIt solution:

code:
$aFile = FileReadToArray("C:\Path\To\File.au3")

$hOutFile = FileOpen("C:\Path\To\New\File.au3", 1)

For $i = 0 To UBound($aFile) - 1
	FileWriteLine($hOutFile, $aFile[$i])
	FileWriteLine($hOutFile, "Sleep(500)")
Next

FileClose($hOutFile)

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

Hughmoris posted:

I'm a complete beginner with programming and I need a little insight on how to tackle a simple work problem. Ideally I'd like to use AutoIt to tackle this although Ithaqua was kind enough to show me a Powershell solution.

I have a text file, of unknown length, composed of AutoIt code. What I want to do is insert Sleep(xxx) between each line of code. It currently looks like this:
code:
Mouseclick 1
Mouseclick 1
Send("foobar")
Mouseclick 1
Mouseclick2
etc...
I'd like it to look like:
code:
Mouseclick 1
Sleep(500)
Mouseclick 1
Sleep(500)
Send("foobar")
Sleep(500)
Mouseclick 1
Sleep(500)
Mouseclick2
etc....
I've learned how to read in a text file, and loop over its contents line by line. I was thinking I could read in a line, copy it to a new file, then write Sleep(xxx) to new file, then read in next line etc... but I'm getting confused with filehandles and file location etc...

Any ideas?

Get a programmer's notepad, like Notepad++, which has find and replace that supports multiple lines. Then, replace every newline with newline Sleep(500) newline. You can copy the newline character by moving your cursor to the end of the line, then holding shift press right. Your cursor should end up on the next line. Ctrl-c, ctrl-v into find/replace fields.

You don't need a script for this :colbert:

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy
Or vim: :%s/$/\rSleep\(500\)/g

KoRMaK
Jul 31, 2012



Amazing, there is a .net fiddle.

Hughmoris
Apr 21, 2007
Let's go to the abyss!

Thermopyle posted:

AutoIt solution:

code:
$aFile = FileReadToArray("C:\Path\To\File.au3")

$hOutFile = FileOpen("C:\Path\To\New\File.au3", 1)

For $i = 0 To UBound($aFile) - 1
	FileWriteLine($hOutFile, $aFile[$i])
	FileWriteLine($hOutFile, "Sleep(500)")
Next

FileClose($hOutFile)

Thanks for this. I haven't explored AutoIt's arrays yet but I'll try and break this down today and learn a little.

Volmarias posted:

Get a programmer's notepad, like Notepad++, which has find and replace that supports multiple lines. Then, replace every newline with newline Sleep(500) newline. You can copy the newline character by moving your cursor to the end of the line, then holding shift press right. Your cursor should end up on the next line. Ctrl-c, ctrl-v into find/replace fields.

You don't need a script for this :colbert:

This type of solution didn't even cross my mind. Thanks!

Bognar posted:

Or vim: :%s/$/\rSleep\(500\)/g

This makes my eyes hurt. It reminds me of my short-lived experience in trying to learn Perl.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Hughmoris posted:

This makes my eyes hurt. It reminds me of my short-lived experience in trying to learn Perl.

If you pick up a little bit of vim parlance, it's not that bad. In VIM you can issue commands by starting them off with a colon. One of the commands you can do is a search and replace, which takes the form:

:s/<searchtext>/<replacetext>

By default, this only works on one line and only on the first occurrence of each line. You can use %s at the beginning to make it work on every line and /g at the end to replace all occurrences on each line instead of just the first one, so to find and replace the entire file you can use:

:%s/<searchtext>/<replacetext>/g

So, the command I gave you (:%s/$/\rSleep\(500\)/g) is a search and replace - searching for $ and replacing it with \rSleep\(500\).

Now, those commands use regular expression syntax, so I'm not actually replacing '$' characters. In regular expressions, '$' means the end of a line. The end of a line isn't really text that can be replaced, so the replacement text just gets appended.

What we want to append at the end of each line is a newline (\r) and the string 'Sleep(500)'. Of course, since we're still utilizing regex syntax, we'll have to escape our parentheses, e.g. Sleep\(500\). Put it all together and you get:

:%s/$/\rSleep\(500\)/g
or
"replace every occurrence of the end of a line with a newline and the string 'Sleep(500)'."



EDIT: In retrospect, the /g isn't necessary since there will only ever be one occurrence of the end of a line in each line.

Bognar fucked around with this message at 16:08 on Jul 29, 2014

TheEffect
Aug 12, 2013
I'm trying to open all files in a certain folder. They're all shortcuts and the path is different on every machine, so I just want to place a batch file in the folder and have it open all shortcuts inside. So far I have-
code:
SET Directory=%~dp0
Start "" /b "%Directory%Shortcut.lnk"
But, even though Windows is telling me it's the correct path, it still says that the file isn't found.

I've also tried this-

code:
SET Directory=%~dp0
Start "" /b %Directory%Shortcut.lnk
and

code:
SET Directory=%~dp0
Start /b %Directory%Shortcut.lnk
Yes, the paths do have spaces in them.

Any ideas?

Sedro
Dec 31, 2008
Is your "certain folder" the desktop? Shift-right click on the shortcut, "Copy as Path" and look at its value. Chances are it exists in a different directory than whatever %~dp0 resolves to.

TheEffect
Aug 12, 2013

Sedro posted:

Is your "certain folder" the desktop? Shift-right click on the shortcut, "Copy as Path" and look at its value. Chances are it exists in a different directory than whatever %~dp0 resolves to.

Thank you! The files had .exe at the end of their names even though they are shortcuts, so I was omitting the .exe when it should've been Shortcut.exe.lnk. Checking the path per your suggestion helped me figure this out. Thanks again.

Edit-
How would I go about opening all files that are shortcuts without specifying each one? Or even all files that start with a certain word?

VV In that scenario would "%~dp0" still not work if the batch file is placed within the folder? VV

TheEffect fucked around with this message at 22:27 on Jul 29, 2014

Sedro
Dec 31, 2008
Cool. The other trick is that shortcuts on the desktop might not actually be on *your* desktop, they could be in the desktop of "all users"/the public user.

nielsm
Jun 1, 2009



TheEffect posted:

VV In that scenario would "%~dp0" still not work if the batch file is placed within the folder? VV

No, the user's view of the "Desktop" folder is a merged view of two physical directories, the user desktop and the shared desktop. You can't interact with the shell's virtual "Desktop" folder from the commandline like this.

Edit: However a Powershell script could probably create an IShellFolder object to enumerate the objects in the virtual folder. The downside to doing that is additional complexity in working with shell folders, and that the Desktop folder also has things like the Recycle Bin, My Computer and Network Neighborhood objects contained.

nielsm fucked around with this message at 21:46 on Jul 29, 2014

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies
For a CS1 class, I want to wrap a python installation and some modules into a custom exe that I'd distribute to the students and they'd use. Essentially Python(x,y) but more customized to my means and as simply as humanly possible to have a specific version of python and specific modules (without any chance of deslecting a module) as this is for students who have tried to run a bat file inside a zip before so I really want to make it as impossible to mess up as possible.

What would be the best way to go about it? (This is for windows, as at least Mac starts with Python so all we need is just a .dmg for modules which already exists)

Master_Odin fucked around with this message at 03:09 on Jul 30, 2014

TheresaJayne
Jul 1, 2011

Bognar posted:

If you pick up a little bit of vim parlance, it's not that bad. In VIM you can issue commands by starting them off with a colon. One of the commands you can do is a search and replace, which takes the form:

:s/<searchtext>/<replacetext>

By default, this only works on one line and only on the first occurrence of each line. You can use %s at the beginning to make it work on every line and /g at the end to replace all occurrences on each line instead of just the first one, so to find and replace the entire file you can use:

:%s/<searchtext>/<replacetext>/g

So, the command I gave you (:%s/$/\rSleep\(500\)/g) is a search and replace - searching for $ and replacing it with \rSleep\(500\).

Now, those commands use regular expression syntax, so I'm not actually replacing '$' characters. In regular expressions, '$' means the end of a line. The end of a line isn't really text that can be replaced, so the replacement text just gets appended.

What we want to append at the end of each line is a newline (\r) and the string 'Sleep(500)'. Of course, since we're still utilizing regex syntax, we'll have to escape our parentheses, e.g. Sleep\(500\). Put it all together and you get:

:%s/$/\rSleep\(500\)/g
or
"replace every occurrence of the end of a line with a newline and the string 'Sleep(500)'."



EDIT: In retrospect, the /g isn't necessary since there will only ever be one occurrence of the end of a line in each line.

Well interesting to learn about the /fixed but when i was taught vi it was taught as
:g/search term/s//replace term/g

Extortionist
Aug 31, 2001

Leave the gun. Take the cannoli.

Bognar posted:

What we want to append at the end of each line is a newline (\r) and the string 'Sleep(500)'.

On Windows systems a newline is \r\n, not just \r. Don't know how much it'd matter in this case, but generally it's a good idea to make sure they're correct for the system--some Windows programs will account for whatever format correctly, but e.g. throwing a \r when you need a \n in Linux will break things.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Extortionist posted:

On Windows systems a newline is \r\n, not just \r. Don't know how much it'd matter in this case, but generally it's a good idea to make sure they're correct for the system--some Windows programs will account for whatever format correctly, but e.g. throwing a \r when you need a \n in Linux will break things.

Actually, in non-Windows systems the newline is typically represented by \n, however Vim is a bit different. In substitutions, \n represents <NUL> while \r represents <NL> or newline. Whether the newline gets turned into \n or \r\n is determined by your fileformat setting, which can be changed by using:

:set fileformat=unix
:set fileformat=dos

Gounads
Mar 13, 2013

Where am I?
How did I get here?

Master_Odin posted:

For a CS1 class, I want to wrap a python installation and some modules into a custom exe that I'd distribute to the students and they'd use. Essentially Python(x,y) but more customized to my means and as simply as humanly possible to have a specific version of python and specific modules (without any chance of deslecting a module) as this is for students who have tried to run a bat file inside a zip before so I really want to make it as impossible to mess up as possible.

What would be the best way to go about it? (This is for windows, as at least Mac starts with Python so all we need is just a .dmg for modules which already exists)

I've had some good luck using pyinstaller http://www.pyinstaller.org/ to distribute an app internally in our company before.

That worked great the first time, but updates sucked. I might have just been doing something wrong, but there were always weird upgrade issues, so in the end, we ended up just installing python all around.

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

Gounads posted:

I've had some good luck using pyinstaller http://www.pyinstaller.org/ to distribute an app internally in our company before.

That worked great the first time, but updates sucked. I might have just been doing something wrong, but there were always weird upgrade issues, so in the end, we ended up just installing python all around.
I'm not distributing an app though, I want to make a custom installer around Python and a few modules, students install that and then they can work in Python. I'm not turning a python script into a standalone installation, just modifying an install process.

We have been using Python(x,y) in the past as it's "easy", but it's kind of too large (especially with everyone downloading a 700mb file all at once, makes the setting up lab really slow). I figure I'll have to use some Windows installer script language, but I don't know what's the best one or anything really.

SurgicalOntologist
Jun 17, 2004

It's not what you're looking for exactly, but Miniconda might be a nice alternative to Python(x,y) since it doesn't come with all the Anaconda packages. You can then distribute a little script that installs the packages you need them to have.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Master_Odin posted:

(especially with everyone downloading a 700mb file all at once, makes the setting up lab really slow)

You have everyone in the same place, right? Why not make it available on a network drive, or pass some USB keys around?

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

Bognar posted:

You have everyone in the same place, right? Why not make it available on a network drive, or pass some USB keys around?
USB keys isn't an option as there is a point where there are 4 labs going on at the same time in 4 different rooms not near each other at all. (average is 2 labs at the same time).

Network drive is an alright idea, but I'd still like to get away from Python(x,y) as we use ~10/~110 of their modules and there's no point downloading all of it, waiting for the slow installation, etc.

This is a class that has all ranges of people familiar with using a computer from really good to not knowing what a zip file is. We've been using Python(x,y) and a bat file in a zip and too many people have had issues with trying to run the bat in the zip (so it fails) and then messing up their environment which means there's un-installations and things and it's so slow I'd rather improve it, especially for the students that are very slow to ask for help.

Kenishi
Nov 18, 2010

Master_Odin posted:

For a CS1 class, I want to wrap a python installation and some modules into a custom exe that I'd distribute to the students and they'd use. Essentially Python(x,y) but more customized to my means and as simply as humanly possible to have a specific version of python and specific modules (without any chance of deslecting a module) as this is for students who have tried to run a bat file inside a zip before so I really want to make it as impossible to mess up as possible.

What would be the best way to go about it? (This is for windows, as at least Mac starts with Python so all we need is just a .dmg for modules which already exists)

WinRar has SFX which is a self extracting exe. You can also set the SFX file to run commands/program after extraction. I would use the Python MSI installer and the administractive commands to do a silent install of Python after the directory is extracted. I'm not sure but the SFX might be able to run a BAT file which you can queue up to do all the tasks you need post-extract.

EDIT: Something like this http://windowsmatters.com/2011/08/27/using-winrar-sfx-to-create-a-silent-install-package/

nielsm
Jun 1, 2009



If you don't care for Python to be a "properly registered version", i.e. having .py files associated with pythonw.exe etc., then just make a staging install, put the appropriate modules in it, and pack up the entire directory into installer of your choice. It could be a self-extracting archive (WinZip, WinRAR, 7zip, whatever) or a more regular installer e.g. InnoSetup.
The advantage of using InnoSetup (or something else) to make a more regular installer is that you can also get an uninstaller for almost free, to allow your students to remove the package from Windows control panel, and it would also let you put icons in the Start menu/on the desktop, for whatever appropriate programs or scripts.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

nielsm posted:

If you don't care for Python to be a "properly registered version", i.e. having .py files associated with pythonw.exe etc.

You can do this with a batch script, too, if you can get the directory you extracted to:

code:
set PYDIRECTORY=C:\YourDirectoryHere
assoc .py=Python.File
ftype Python.File="%PYDIRECTORY%" %1

Workaday Wizard
Oct 23, 2009

by Pragmatica
Hello,

I am trying to toggle the loudness equalizer on my speakers with code using C++.


Currently I am able to get the default playback speakers using IMMDeviceEnumerator but I can't find where the enhancements are configured.
The closest thing I got on MSDN is the documentation for System Effects Audio Processing Objects and Audio Drivers Interfaces.

Does anyone have any tips how to proceed? Also is it possible to monitor API calls for system dialogs such as this one (rundll.exe)? If so, how?

Xeom
Mar 16, 2007
Is it common when starting out with programming to spend a lot of time solving little issues, and figuring out better ways to write things? Like I was trying to come up with a algorithm for a calculator now I am second guessing it because I think there might be a better way to do it.

Feels like a lot of back and forth, is this normal?

Jewel
May 2, 2009

Xeom posted:

Is it common when starting out with programming to spend a lot of time solving little issues, and figuring out better ways to write things? Like I was trying to come up with a algorithm for a calculator now I am second guessing it because I think there might be a better way to do it.

Feels like a lot of back and forth, is this normal?

Basically 80%+ of programming.

GOOD TIMES ON METH
Mar 17, 2006

Fun Shoe
Do you guys have any recommendations for a combination of language and database is especially good at handling fairly simple mathematics in large multidimensional arrays? Right now I work with a proprietary language that is pretty similar to old Fortran and has its own database system that it can pull from and write to. But it is now several decades old and really isn't maintained at all anymore, so it will forever be stuck in 32 bit single-threaded world, so I am starting to look into the idea of rewriting everything more modern.

Basically, I want to be able to multiply giant gigabite sized arrays that are five or six dimensions by other arrays that have the similar dimension and get out a new array as fast as possible, ideally with code that is fairly simple to understand by non-programmers. I know bizzaro-Fortran and some Java and a tiny bit of C++ but I am generally a clean slate. My education is economics and am pretty good at figuring stuff out, but not a trained programmer by any means.

I have been looking at Julia because of this paper and maybe tie it in with SQLite as a first step to see how fast everything is. Any suggestions?

GOOD TIMES ON METH fucked around with this message at 02:34 on Aug 1, 2014

ultrafilter
Aug 23, 2007

It's okay if you have any questions.


Matlab is pretty standard in economics. It's not free, but if that's not a problem, it's worth looking into.

GOOD TIMES ON METH
Mar 17, 2006

Fun Shoe
Matlab is pretty slow at this kind of stuff from what I've read. For instance, I have data for the amount of fuel consumed by the transportation sector in the US by six different dimensions: 20 different vehicle types, 5 transportation types (commuting, freight, etc), 50 states, 4 fuel types, 30 years. I want to get the amount of emissions in each possible category (eg: SUV Commuters in Alaska using gasoline in 1990) by multiplying by a emissions coefficient that has the same dimensions. So I am doing a simple x times y = z equation but by whatever ridiculous exponent that all comes out to. Then I am doing to do similar equations a 1000 different times for various other parts of the program.

Some of this seems like it could be handled directly in the database itself but other equations in this program get a bit more complex (OLS, logs, etc).

Nippashish
Nov 2, 2005

Let me see you dance!

Goetta posted:

Matlab is pretty slow at this kind of stuff from what I've read. For instance, I have data for the amount of fuel consumed by the transportation sector in the US by six different dimensions: 20 different vehicle types, 5 transportation types (commuting, freight, etc), 50 states, 4 fuel types, 30 years. I want to get the amount of emissions in each possible category (eg: SUV Commuters in Alaska using gasoline in 1990) by multiplying by a emissions coefficient that has the same dimensions. So I am doing a simple x times y = z equation but by whatever ridiculous exponent that all comes out to. Then I am doing to do similar equations a 1000 different times for various other parts of the program.

Some of this seems like it could be handled directly in the database itself but other equations in this program get a bit more complex (OLS, logs, etc).

Elementwise multiplication of big blocks of numbers is pretty much the thing matlab is best at. Python + numpy is also a good (free) choice and is generally a nicer language to work with, although getting the environment set up can be a bit more work.

EAT THE EGGS RICOLA
May 29, 2008

Master_Odin posted:

For a CS1 class, I want to ...

This is probably not the answer for your situation, but every time I've taught a class lately I've provided a vagrant box so everyone has the exact same dev environment. It saves so much time with getting set up and it stops people from having to deal with machine-specific issues.

SurgicalOntologist
Jun 17, 2004

If getting every last drop of speed is important, I think the Intel MKL libraries are your best bet. Both MATLAB and numpy (the Python array library) can be linked to MKL under the hood, with enough patience. MATLAB probably does some optimizations on top of that. And then there are various ways to get optimizations of numpy expressions, maybe check out this talk that summarizes some of them:

https://www.youtube.com/watch?v=cRb96NEHW4I

Honestly though I'd guess your database accesses are the bottleneck. I tried a multiplication with dimensions (20, 5, 50, 4, 30, 1000), it took about 5 s with numpy + MKL. Plus it doesn't sound like a computation you need to do many times, unless that data is always changing.

Symbolic Butt
Mar 22, 2009

(_!_)
Buglord

Goetta posted:

Basically, I want to be able to multiply giant gigabite sized arrays that are five or six dimensions by other arrays that have the similar dimension and get out a new array as fast as possible, ideally with code that is fairly simple to understand by non-programmers.
Alternatively if you learn SQL/relational algebra well you can maybe not ever leave the database to do this stuff. :ssh:

No seriously, this was a big point for me on Bill Howe's Introduction to Data Science course, a dirty secret is that DBMS's are pretty fast at doing these kinds of calculations. And you don't even need to think about any serious numeric optimization algorithms or how you'd fit those huge rows in L1 cache...

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

Xeom posted:

Is it common when starting out with programming to spend a lot of time solving little issues, and figuring out better ways to write things? Like I was trying to come up with a algorithm for a calculator now I am second guessing it because I think there might be a better way to do it.

Feels like a lot of back and forth, is this normal?

Yes. Some of this passes with experience, but you'll spend a lot of time having "aha" moments, or learning something new. Part of programming is learning when something is good enough and leaving it alone.

GOOD TIMES ON METH
Mar 17, 2006

Fun Shoe
Thanks for the suggestions guys. Julia is fairly similar to MatLab so I will keep going in that direction for now and start playing around with databases.

Star War Sex Parrot
Oct 2, 2003

EAT THE EGGS RICOLA posted:

This is probably not the answer for your situation, but every time I've taught a class lately I've provided a vagrant box so everyone has the exact same dev environment. It saves so much time with getting set up and it stops people from having to deal with machine-specific issues.
Yeah most intro CS classes at my university just provide a standardized VirtualBox VM with the required tools: runs on Windows, OS X, and Linux so instructors don't have to worry about whatever goofy OS their students might be running.

Kosani
Jun 30, 2004
Ni ni.
I'm currently working through exercise #32 from the Learn C The Hard Way tutorials, available here: http://c.learncodethehardway.org/book/ex32.html

I am confused about the following iteration macro that the writer makes for his linked list library:

code:
#define LIST_FOREACH(L, S, M, V) ListNode *_node = NULL;\
    ListNode *V = NULL;\
    for(V = _node = L->S; _node != NULL; V = _node = _node->M)

#endif
What is the purpose of the double assignment in the for loop? Shouldn't this work the same way? :

code:
#define LIST_FOREACH(L, S, M, V) 
    ListNode *V = NULL;\
    for(V = L->S; V != NULL; V =V->M)

#endif
Thanks to anyone kind enough to help.

Kosani fucked around with this message at 02:17 on Aug 2, 2014

Adbot
ADBOT LOVES YOU

Vanadium
Jan 8, 2005

If the user reassigns V, you've lost control of the loop. If they reassign _node, it's their own fault for touching a variable with a name starting with an underscore, they should know better.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply