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
Malloc Voidstar
May 7, 2007

Fuck the cowboys. Unf. Fuck em hard.

baquerd posted:

First you read the file into a data structure like a Vector. Then you give the Vector to the JComboBox's constructor and add your JComboBox to a JFrame set to display at the right size.
don't ever use Vectors

Adbot
ADBOT LOVES YOU

Eggnogium
Jun 1, 2010

Never give an inch! Hnnnghhhhhh!

Aleksei Vasiliev posted:

don't ever use Vectors

Care to elaborate?

Contra Duck
Nov 4, 2004

#1 DAD
Vector used to be the one to use back in the Java 1.0/1.1 days but when collections framework was introduced in 1.2, ArrayList became the better option in most cases. Vector still has a small amount of use since it's threadsafe by default (ArrayLists are not threadsafe on their own but it's trivial to create a threadsafe wrapper for one) and because it gives you a little bit more fine-grained control over its internal behaviour but in most situations neither of these things are important so you might as well go with ArrayList which is far more common and provides better performance.

Contra Duck fucked around with this message at 08:01 on Apr 28, 2011

mcw
Jul 28, 2005

Contra Duck posted:

Vector used to be the one to use back in the Java 1.0/1.1 days but when collections framework was introduced in 1.2, ArrayList became the better option in most cases. Vector still has a small amount of use since it's threadsafe by default (ArrayLists are not threadsafe on their own but it's trivial to create a threadsafe wrapper for one) and because it gives you a little bit more fine-grained control over its internal behaviour but in most situations neither of these things are important so you might as well go with ArrayList which is far more common and provides better performance.

While we're on the subject, why does EclipseLink always return multiple results as a Vector?

Kilson
Jan 16, 2003

I EAT LITTLE CHILDREN FOR BREAKFAST !!11!!1!!!!111!
Also, don't use the default Stack, because it extends from Vector, and is retarded. (Unless you need a stack with random access, which means you really should be using some other structure anyway)

ZeroConnection
Aug 8, 2008
Yeah i solved it , thanks ! I got a new problem though !

Currently I'm trying to do a display function right , so here goes:
I tried using Jtables but I failed , so I'm trying to display some values into a JTextArea.

So I have a class called Modules.It has 3 arraylists to store some variable. One example is the Student_ID list where I would store all the students name into the array list. The other arraylist is the incourse_score list and the final_exam list.

Then later on when I made an object from the class Modules ,I have serialized it to a .data file.

Now I have successfully deserialized it into a new form . This new form would deserialize all the modules that I have and so I think the Modules is already loaded up into the memory, and now I am trying to pass the arraylist size into the JText Area to view it.

I tried to do this but it does not work:

for( int count =1 ; count>=Module_Array[1].Student_ID_List.size() ; count++){
jTextArea1.append(Module_Array[1].Student_ID_List.get(count)) ;
}

then I tried to first pass the arraylist size (Student_ID_List.size() to a new integer and use that integer(Limit) to do this :
for( int count =1 ; count>=Limit ; count++){
jTextArea1.append(Module_Array[1].Student_ID_List.get(count)) ;
}

but when I try to do this :
int Limit;
Limit=Module_Array[1].Student_ID_List.size() , the same error message came up.
//Quick note: Module_Array[1] = where i saved the first deseriallized object into.
Student_ID_List = belongs to the object ,shouldn't be any problems right?

My error is that every time I compile it , I get :


Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at student_management.Module_Search_Box.<init>(Module_Search_Box.java:126)
at student_management.Main$1.run(Main.java:33)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

:suicide:

edit: there might be something wrong when i try to serialize the object into a file , so I wonder is it wrong to name the file with the .data extension, if i'm wrong then what extension should I use?


edit 2: A simplified code of me serializing an object
//before that
Modules New_Module = new Modules ();
try {

FileOutputStream f_out = new FileOutputStream("Module.tmp");

ObjectOutputStream obj_out = new ObjectOutputStream (f_out);
obj_out.writeObject ( New_Module);
obj_out.close();
System.out.println( "Serializing an Object Creation completed successfully.");
}
catch (IOException err) {

System.err.println("Object-Output - Error writing to file\n" +err.getMessage()) ;
}

ZeroConnection fucked around with this message at 18:00 on Apr 28, 2011

Chairman Steve
Mar 9, 2007
Whiter than sour cream
You should read Sun's documentation on serialization[1]. I suspect your list isn't getting serialized. Also, for the benefit of anyone who has to read your code, learn about Java's variable naming conventions[2].

1. http://java.sun.com/developer/technicalArticles/Programming/serialization/
2. http://download.oracle.com/javase/tutorial/java/nutsandbolts/variables.html

Chairman Steve
Mar 9, 2007
Whiter than sour cream

Contra Duck posted:

...you might as well go with ArrayList which is far more common and provides better performance.

Unless random access is of dire importance, isn't a LinkedList the best to use, since you don't have to deal with array resizing?

baquerd
Jul 2, 2007

by FactsAreUseless

Aleksei Vasiliev posted:

don't ever use Vectors

Thread safe, as has already been mentioned. When you're working on a bunch of RMI infrastructure and large amounts of transactional data, it's essential. Worrying about performance of your underlying data structures is rarely a good use of time these days if you've made good base choices (eg. list vs. hashset).

brosmike
Jun 26, 2009

Chairman Steve posted:

Unless random access is of dire importance, isn't a LinkedList the best to use, since you don't have to deal with array resizing?

This Stack Overflow thread does a pretty decent job of explaining it. To answer your question, no, in most cases array resizing isn't really a big deal - even with it, appending to an ArrayList is an amortized constant time operation. For people unfamiliar with time complexity analysis, that means that the total amount of time it takes to perform N append operations on an ArrayList will be about a constant factor times N, even though it will occasionally need to copy the whole list.

To summarize the Stack Overflow thread, the main theoretical tradeoffs are that ArrayLists are fast at random access but slow at inserting or removing from the middle of the list, and LinkedLists are slow at random access but can insert or remove an element they have visited sequentially very quickly.

In practice, ArrayLists are the more typical default. The main reason is that random access is usually much more useful than fast mid-traversal insertion, but they also have the advantage of typically being faster in practice; most hardware can generally look at the next cell in array much faster than it can look at the next random pointer in god-knows-what-bit-of-memory. This has especially noticeable effects if you're doing something like traversing large lists - your computer can often store a whole array in a fast cache before trying to traverse it, but it can't do the same for the linked list since the nodes are scattered throughout memory.

That said, there are many applications for which LinkedLists are more appropriate - for example, algorithms which can use the fast insertion property, or in rare cases where the consistency of never resizing is more valuable than the typically better average performance of an ArrayList.

In general, unless you're working with large lists it doesn't matter much anyway - usually the list performance won't be what's holding your application back unless it's storing a significant chunk of data. Don't lose sleep over it unless profiling shows that it's actually a problem.

Contra Duck
Nov 4, 2004

#1 DAD

Chairman Steve posted:

Unless random access is of dire importance, isn't a LinkedList the best to use, since you don't have to deal with array resizing?

I was only comparing Vector to ArrayList because they are just different implementations of the same data structure. Usual rules about which data structure is best for any given application should still apply.

ZeroConnection
Aug 8, 2008

Chairman Steve posted:

You should read Sun's documentation on serialization[1]. I suspect your list isn't getting serialized. Also, for the benefit of anyone who has to read your code, learn about Java's variable naming conventions[2].

1. http://java.sun.com/developer/technicalArticles/Programming/serialization/
2. http://download.oracle.com/javase/tutorial/java/nutsandbolts/variables.html

:hfive:
Thanks for the help!

Malloc Voidstar
May 7, 2007

Fuck the cowboys. Unf. Fuck em hard.

baquerd posted:

Thread safe, as has already been mentioned. When you're working on a bunch of RMI infrastructure and large amounts of transactional data, it's essential. Worrying about performance of your underlying data structures is rarely a good use of time these days if you've made good base choices (eg. list vs. hashset).
you can get a synchronized List, or use a CopyOnWriteArrayList if its bizarre characteristics are good for you

but I don't know that much about threadsafety so I'll shut up now

Lexical Unit
Sep 16, 2003

I am a complete loving idiot when it comes to Java. I haven't used the language in like 7 years. And I've never worked with jar files before. What am I doing wrong?

code:
$ java -version
java version "1.6.0_22"

$ ls .
foo.java

$ ls /path/to/lib
PKG.jar

$ jar tf /path/to/lib/PKG.jar
META-INF/
META-INF/MANIFEST.MF
bar/
bar/baz.java
bar/baz.class

$ cat foo.java
package PKG.bar.baz;

class foo
{
	public static void main(String[] args)
	{
	
	}
}
	
$ export CLASSPATH=".;/path/to/lib/PKG.jar"
$ javac foo.java

$ java foo
Exception in thread "main" java.lang.NoClassDefFoundError: foo
...

$ java -cp "$CLASSPATH" foo
Exception in thread "main" java.lang.NoClassDefFoundError: foo
...

$ java -cp . foo
Exception in thread "main" java.lang.NoClassDefFoundError: foo (wrong name: PKG/bar/baz/foo)
...
Edit: I copy/pasted this wrong, I was using the package command instead of the import command. Oops.

Lexical Unit fucked around with this message at 16:32 on Apr 29, 2011

covener
Jan 10, 2004

You know, for kids!

Lexical Unit posted:

bar/baz.class
...
$ cat foo.java
import PKG.bar.baz;
...
Exception in thread "main" java.lang.NoClassDefFoundError: foo (wrong name: PKG/bar/baz/foo)

No PKG on the import if your class is bar.baz and lives in bar/baz on the classpath. Also colon is the separate on unix for the classpath.

Lexical Unit
Sep 16, 2003

covener posted:

No PKG on the import if your class is bar.baz and lives in bar/baz on the classpath. Also colon is the separate on unix for the classpath.
Noted on the :, I thought it was weird that all the tutorials were using ;. As for bar/baz, it's not a path. It's something inside a jar file.

Oh DUH! I should be using the import command, not the package command :downs:

Lexical Unit fucked around with this message at 16:29 on Apr 29, 2011

covener
Jan 10, 2004

You know, for kids!

Lexical Unit posted:

Noted on the :, I thought it was weird that all the tutorials were using ;. As for bar/baz, it's not a path. It's something inside a jar file.

Oh DUH! I should be using the import command, not the package command :downs:

java doesn't care what jar it comes from, it's still bar.baz when it lives in PKG.jar.

Malloc Voidstar
May 7, 2007

Fuck the cowboys. Unf. Fuck em hard.
belated response:

Nippashish posted:

[Viola-Jones object detection, normalized cross-correlation]
oh god I can't figure out any of this :(
Though searching has led me to find various stuff that i also don't understand, i need to go deeper, so thanks!

Thermopyle posted:

That sounds like a fun project!

I may try that myself...
It is fun, as long as you like Bejeweled-type games at least a bit. Doing it really badly but still having it work is apparently pretty easy, which could help if you didn't know what the gently caress. (note: do not use that code. that domain is totally mislabeled)

ShardPhoenix posted:

maybe take a saved image of each type of gem and subtract it from the gem you're looking at (you should be at least able to find where the gems are on the screen).
I'll try this soon. It probably won't help with Blitz's annoyingly-varied fast-moving gems, but it might be more useful than color averaging in a game like Puzzle Quest: CotW or PQ2. And yeah, I can find out where the gems are onscreen; my bots for PQ and Blitz even work at arbitrary resolutions.

Jabor posted:

I think part of the issue is you're looking at hue. Don't. It's irrelevant. Distinguishing shape is much faster and easier, and gives you all the information you need. Greyscale, threshold, perhaps some denoising, and then it's trivial for any image classification algorithm.
I don't know any image classification algorithms :saddowns:
But for some reason I hadn't thought of doing any pre-processing on the gem images I'm capturing, so thanks for making me realize that I've somehow missed a massive area of improvement.
(Not using hue'd probably die in PQ2 -- they decided to make four of the gems exactly the same shape, bar a black-colored symbol in the middle -- but PQ2 is a lovely game that's bad so I don't care all that much.)

Nippashish
Nov 2, 2005

Let me see you dance!

Aleksei Vasiliev posted:

oh god I can't figure out any of this :(

Viola-Jones is complicated, but NCC is really easy (although if you looked it up on wikipedia I can understand why you didn't get it, their explanation is pretty opaque).

Basically, using NCC goes like this (it's roughly the same as what ShardPhoenix suggested, although superficially different):
  1. Collect templates for each gem you want to recognize, it will probably work best if you black out the non-gem pixels in the template.
  2. Normalize each template so the squares of the pixel values sum to 1.
Then you would recognize gems as follows:
  1. Find the gem you want to recognize and grab a patch of pixes the same size as the template.
  2. Normalize this patch so the squares of the pixel values sum to 1.
  3. Pointwise multiply the target image with your template and sum I.e, compute sum_{i=1}^n x_i*t_i where x_i's are pixels in your target image, and t_i's are pixels in your template.
  4. Repeat step 3 for each template. The template which gives the largest value for step 3 is the best match to the target.
This approach treats the target image and the template as vectors and measures the angle between them. Step 3 is a dot product, and cos(theta) = x dot t when x and t are unit vectors. The normalize steps above make sure that your template and the patch you're comparing with are unit vectors. cos(theta) is largest when theta is near zero, so maximizing cos(theta) finds the template that is closest to the target.

Aleksei Vasiliev posted:

(Not using hue'd probably die in PQ2 -- they decided to make four of the gems exactly the same shape, bar a black-colored symbol in the middle -- but PQ2 is a lovely game that's bad so I don't care all that much.)
I disagree with Jabor's suggestion to ignore hue. Ignoring color is pretty common when trying to recognize objects in images but, it's not because color doesn't have any information. In photographs (which is what people usually care about) color is very hard to deal with because different lighting conditions/camera properties/phases of the moon/etc can cause the color values for pixels to vary dramatically. It turns out that perceptually similar colors and optically similar colors don't really match up well and it is very difficult to design algorithms that account for the perceptual quirks of human vision.

That said, you are not dealing with photographs. The colors in your situation are very controlled; presumably Bejeweled is not using a perceptually similar but optically different shade of blue each time it shows a blue gem. I would handle color here by treating each channel separately and combining the results. You could, for example, do NCC as I described above on each channel and sum the results to get a final score for each template.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Nippashish posted:

I disagree with Jabor's suggestion to ignore hue. Ignoring color is pretty common when trying to recognize objects in images but, it's not because color doesn't have any information. In photographs (which is what people usually care about) color is very hard to deal with because different lighting conditions/camera properties/phases of the moon/etc can cause the color values for pixels to vary dramatically. It turns out that perceptually similar colors and optically similar colors don't really match up well and it is very difficult to design algorithms that account for the perceptual quirks of human vision.

That said, you are not dealing with photographs. The colors in your situation are very controlled; presumably Bejeweled is not using a perceptually similar but optically different shade of blue each time it shows a blue gem. I would handle color here by treating each channel separately and combining the results. You could, for example, do NCC as I described above on each channel and sum the results to get a final score for each template.

Even in the case of Bejeweled, there's still quite a bit of chroma noise. Here's an example screenshot from what I gather to be a version with fewer fancy effects:



I'd expect the flashes in particular to be a big hassle if you're trying to work off chroma.

And after a basic greyscale+threshold:



The octagons and circles are a little ambiguous (and you'd probably want to fall back to hue for those), but everything else is trivially distinguishable. Fair enough, NCC on the original image would probably distinguish gems just fine. But that's three times the work for a similar result.

Paolomania
Apr 26, 2006

Yeah I have to agree with Jabor, it looks like you can just sum color components in a central sub-rectangle (i.e. take average without the divide) and even with flashes you will get some signature such as red-high, green-high, red/blue-high, etc. For problematic cases you can then do a more expensive second pass look at something else such as proximity to templates for matches to all-high (white), but culled to look at only a few possible cases based on hue.

mcw
Jul 28, 2005
On a scale of 1 to awesome, how awesome is JavaOne? Registration opened recently for this year's event, and even though my employer won't send me, I'm thinking of going on my own.

Deep Winter
Mar 26, 2010
Hypotheticaly speaking, would it be against the rules to ask for help on my java programming final?

Janitor Prime
Jan 22, 2004

PC LOAD LETTER

What da fuck does that mean

Fun Shoe

Deep Winter posted:

Hypotheticaly speaking, would it be against the rules to ask for help on my java programming final?

Hypotheticaly you could :getout:. But that's mean, so I'll just say that I don't think anyone in CoC would help you.

Piss Man 94
Jun 11, 2003
Depends on the kind of help you want. I don't think theres anything wrong with giving you some ideas that you can work off of.

epswing
Nov 4, 2003

Soiled Meat
Don't ask to ask, just ask! You'll either be ridiculed or aided or both. It's on the internet, what do you have to lose, really. :)

Paolomania
Apr 26, 2006

Deep Winter posted:

Hypotheticaly speaking, would it be against the rules to ask for help on my java programming final?

That depends, what are the rules of your java programming final?

crazyfish
Sep 19, 2002

brosmike posted:

In general, unless you're working with large lists it doesn't matter much anyway - usually the list performance won't be what's holding your application back unless it's storing a significant chunk of data. Don't lose sleep over it unless profiling shows that it's actually a problem.

We actually ran into a bug using linked lists where they got large enough that memory fragmentation became an issue, so the gc thread wound up taking forever to free the memory after the object was destroyed (especially if parts of the tenured generation were swapped to disk). Switching to ArrayList fixed the problem instantaneously.

Not that this changes things dramatically, just pointing out some of the random quirks of the implementation :)

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Deep Winter posted:

Hypotheticaly speaking, would it be against the rules to ask for help on my java programming final?

Why not ask your teacher? Teachers are cool.

Howmuch
Apr 29, 2008
Hopefully someone can point me in the right direction with this.

I'm trying to add an array to a JList. I've created a DefaultListModel(completeModel) for the JList, but all that shows up in the JList is: [Ljava.lang.String;@741827d1

any ideas?

code:
public void showCompleteList()
	{
		String[] normalArray = controller.getEverybody();
		for(int i = 0; i < normalArray.length; i++)
		{
			completeModel.add(i, normalArray);
		}
	}

covener
Jan 10, 2004

You know, for kids!

Howmuch posted:

Hopefully someone can point me in the right direction with this.

I'm trying to add an array to a JList. I've created a DefaultListModel(completeModel) for the JList, but all that shows up in the JList is: [Ljava.lang.String;@741827d1

any ideas?

Did you intend to instead have normalArray[i] in your for loop? You're adding the Array object N times, and the output is the .toString() of an array. If you only intended to add the array once, you might xform it into a collection with Arrays#asList

Howmuch
Apr 29, 2008

covener posted:

Did you intend to instead have normalArray[i] in your for loop? You're adding the Array object N times, and the output is the .toString() of an array. If you only intended to add the array once, you might xform it into a collection with Arrays#asList

Thanks for that.

I'm iterating through the array now and place the strings in the model with the .addElement.

Its so much fun staring at the same couple of lines of code for too long and totally missing the obvious.

Clanpot Shake
Aug 10, 2006
shake shake!

I've got a task I'd like to write a script or quick executable to do for me. I'm not sure what the best language to do this in is, but since I have a passing familiarity with STAX (Java XML processor) I figured here would work.

I've got a prohibitively large XML file. For argument's sake, the file is made up of multiple elements called <chapter>. Chapters all have an "id" attribute, and all id attributes are unique. Chapter elements have many sub-elements. What I need to do is take a much smaller XML file that contains only one chapter with an id that matches a chapter in the larger file and replace the large file's version with the one from the smaller file.

What's the best way to approach this? Is Java a good match to do this, or would there be a better language to do this in? Any frameworks I should be aware of?

Stubbs
Oct 24, 2005

You're looking for Groovy.
It's best described "Hey, you got your Python in my Java!".

Use all your favorite Java libraries in a dynamically typed, shell-friendly environment.

Chairman Steve
Mar 9, 2007
Whiter than sour cream

Stubbs posted:

It's best described "Hey, you got your Python in my Java!"

Wouldn't that be Jython?

Partyworm
Jul 8, 2004

Tired of partying
Why does the below code only call repaint() once each time a button is fired? If i put this code (sans action listener) directly into the JFrame object so that it executes immediately at runtime it works perfectly (i.e. calls repaint() 24 times to animate a 2D object).

code:
//assigned to a button object
    public void actionPerformed(ActionEvent event) {
        //do the following after a button is pressed
           for (int i = 0; i < 24; i++) {
              frame.repaint();
                try {
                  Thread.sleep(50);
                    } catch (Exception ex) {}
          }
    }
My only hunch is that the loop gets killed prematurely once the action event expires. But how would I fix that?

Partyworm fucked around with this message at 22:59 on May 7, 2011

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
You basically want to call repaint 24 times at 50-millisecond intervals, right?

Now, the first rule of UI programming is that event handlers should do what the need to and then return quickly - if you have an event handler that takes a second or so to run, then your application isn't processing any more events for that second, your UI isn't being redrawn, basically the user sees your application lock up and become nonresponsive. I would guess that's what's happening here - repaint is being called 24 times, but you only see the results of the last one because the UI doesn't get updated in between.

So Thread.sleep() in an action listener is not a good idea. Instead, to call something at specified intervals, you want to use a timer.

code:
//setup code (``timer'' is a field somewhere)
ActionListener fuckWhyDoesntJavaHaveAnonymousFunctions = 
    new ActionListener() {
  int i = 0;
  public void actionPerformed(ActionEvent e) {
    if(++i < 24)
      frame.repaint();
    else
      timer.stop();
  }
}
timer = new Timer(50, fWDJHAF);

//button action listener
public void actionPerformed(ActionEvent e) {
  timer.start();
}

Partyworm
Jul 8, 2004

Tired of partying

Jabor posted:

code:
    if(++i < 24)

You just blew my mind :aaaaa:

It works now. Yay :)

Red_Fred
Oct 21, 2010


Fallen Rib
Hey guys I'm doing an assignment for my CompSci 101 paper at uni and I'm stuck on a particular method. We need to design a basic elevator algorithm using classes. This is from the elevator class. Please be gentle as I'm new to Java and code.

code:
public void openDoors(Floor other) {
		for (int i = 0; i < people.length; i++) {
			other.incNumPeople(people[i]);
			for (int a = 0; a < people.length; a++) {
				people[a] = people[a + 1];
				if (currentFloorNumber != people[a].getTargetFloor()) {
						addPerson(people[a]);
						for (int b = 0; b < people.length; b++) {
							other.removePerson(people[b]);
						}
				}
			}
		}
	}
I keep getting either nullPointerExceptions or arrayIndexOutOfBounds errors when I run the program. Usually on the if statement.

What am I doing wrong? Let me know if you need more information.

Adbot
ADBOT LOVES YOU

Malloc Voidstar
May 7, 2007

Fuck the cowboys. Unf. Fuck em hard.
code:
for (int a = 0; a < people.length; a++) {
	people[a] = people[a + 1];
if your array has four elements (indexes of 0, 1, 2, 3) then on the last iteration it will attempt to access the fifth element (at index 4) and get gunned down by mangalores crash with an ArrayIndexOutOfBounds

as for the NullPointers, you are attempting to call a method on a null element. Are all of the elements of the array initialized?

pre-post edit: Why do you have a for-loop inside the for-loop, both of which are iterating over the array in the same order?

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