package tsp;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.FontUIResource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import tsp.map.TSPMap;
import tsp.solvers.GeneticSolver;
import tsp.solvers.NearestNeigbourSolver;
import tsp.solvers.Tour;
import tsp.solvers.rnearest.NearestNeigbourRandomizedSolver;
import tsp.util.BestList;
import tsp.util.CitieData;
import tsp.util.delay;

/////////////////////////////////////////////////////////////////////////////////////
//Specifics

//class for file filtering
class CFileFilter extends javax.swing.filechooser.FileFilter
{
	public boolean accept(File f) 
	{
	    if (f.isDirectory()) 
	    {
	    	return true;
	    }
	
	    String name = f.getName().toLowerCase();
		     
		return name.endsWith("xml");
	}

	@Override
	public String getDescription()
	{
		return "XML files";
	}
};

public class TSPApplet extends Applet implements MouseListener
{
	private static final long serialVersionUID = 1L;
	public static final int MAX_POINTS = 2048;
	protected static final int PROCESSOR_COUNT = Runtime.getRuntime().availableProcessors();
	TSPMap map = null;
	TSPApplet self = this;
	int pointsCount = 100;
	int iterationCount = 100;
	int popCount = 50;
	int crossFactor = 40;
	int muteFactor = 20;
	TourDisplay display;
	public JLabel lenLabel;
	JTextField inputPoints = new JTextField();
	JTextField inputIterations = new JTextField();
	JTextField outputDistance = new JTextField();
	JTextField outputTime = new JTextField();
	JTextField inputPop = new JTextField();
	JTextField inputCross = new JTextField();
	JTextField inputMute = new JTextField();
	JSlider inputRnnDegree = new JSlider(JSlider.HORIZONTAL, 1, 100, 1);
	JLabel inputRnnDegreeLabel = null;
	final JButton gridButton = new JButton("Grid");
	final JButton newButton = new JButton("Random");
	final JButton nnButton = new JButton("Nearest Neighbor");
	final JButton rnnButton = new JButton("Random Neighbor");
	final JButton optButton = new JButton("2-opt");
	final JButton gaButton = new JButton("Genetic");
	final JButton gaModButton = new JButton("Genetic-M");
	final JButton stopButton = new JButton("STOP");
	final JButton fromFileButton = new JButton("From file");
	final JButton clearButon = new JButton("Clear");
	Thread worker;
	boolean threadWorking = false;

	private Tour bestTour = null;
	private BestList bestValues = new BestList();
	private JTextArea bestValuesLabel = new JTextArea();
	private long bestTourStarted = 0;
	private String currentTour = "";
	private boolean needToStop = false;

	public TSPApplet() 
	{
		map = null;
		threadWorking = false;
		clearBestTour("");
	}

	public void init() 
	{
		try 
		{
			UIManager.getDefaults().put("Label.font", new FontUIResource("Dialog", Font.PLAIN, 11));
		} 
		catch (Exception e)
		{
			System.out.println("Failed to set font to labels");
			e.printStackTrace();
		}
		// this.setBackground(Color.lightGray);
		display = new TourDisplay(map);
		display.setMinimumSize(new Dimension(400, 640));
		display.setPreferredSize(new Dimension(400, 640));
		lenLabel = new JLabel("Press 'Random', 'Grid' or 'From file' button to start...");
		inputRnnDegreeLabel = new JLabel();
	}

	private void toggleOperationButtons(boolean enabled) {
		nnButton.setEnabled(enabled);
		rnnButton.setEnabled(enabled);
		optButton.setEnabled(enabled);
		gaButton.setEnabled(enabled);
		gaModButton.setEnabled(enabled);
		gridButton.setEnabled(enabled);
		newButton.setEnabled(enabled);
		fromFileButton.setEnabled(enabled);
		clearButon.setEnabled(enabled);
	}

	public void start() 
	{
		this.setBackground(Color.WHITE);
		this.setLayout(new FlowLayout(1, 0, 0));
		JPanel panel = new JPanel();
		panel.setPreferredSize(new Dimension(420, 675));
		panel.setBackground(getBackground());
		panel.add(display);
		Border border = new TitledBorder("Map");
		panel.setBorder(border);
		
		// add mouse listener to capture mouse events
		panel.addMouseListener(this);
		
		this.add(panel);

		JPanel rPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
		rPanel.setPreferredSize(new Dimension(170, 675)); 
		rPanel.setLocation(0, 0);
		panel = new JPanel();
		panel.setBackground(getBackground());
		rPanel.setBackground(getBackground());

		panel.setBorder(new TitledBorder("Parameters"));
		panel.setPreferredSize(new Dimension(170, 180));
		// panel.setBackground(getBackground());
		panel.add(new JLabel("      # of cities:"));
		inputPoints.setPreferredSize(new Dimension(50, 17));
		inputPoints.setText(Integer.toString(pointsCount));
		panel.add(inputPoints);
		panel.add(new JLabel("# of iterations:"));
		inputIterations.setPreferredSize(new Dimension(50, 17));
		inputIterations.setText(Integer.toString(iterationCount));
		panel.add(inputIterations);
		panel.add(new JLabel("Population(GA):"));
		inputPop.setPreferredSize(new Dimension(30, 17));
		inputPop.setText(Integer.toString(popCount));
		panel.add(inputPop);
		panel.add(new JLabel("Cross Factor(GA):"));
		inputCross.setPreferredSize(new Dimension(30, 17));
		inputCross.setText(Integer.toString(crossFactor));
		panel.add(inputCross);
		panel.add(new JLabel("Mute Factor(GA):"));
		inputMute.setPreferredSize(new Dimension(30, 17));
		inputMute.setText(Integer.toString(muteFactor));
		panel.add(inputMute);
		inputRnnDegreeLabel.setAlignmentX(JComponent.CENTER_ALIGNMENT);
		inputRnnDegreeLabel.setPreferredSize(new Dimension(150, 14));
		panel.add(inputRnnDegreeLabel);
		inputRnnDegree.setPreferredSize(new Dimension(150, 20));
		
		inputRnnDegree.addChangeListener(new ChangeListener()
		{
			public void stateChanged(ChangeEvent e) 
			{
				inputRnnDegreeLabel.setText("Degree (NNR): " + inputRnnDegree.getValue());
			}
		});
		panel.add(inputRnnDegree);
		inputRnnDegree.setValue(100);
		inputRnnDegree.setBackground(getBackground());
		rPanel.add(panel);

		panel = new JPanel();
		panel.setBackground(getBackground());
		panel.setBorder(new TitledBorder("Results"));
		// panel.setBackground(getBackground());
		panel.setPreferredSize(new Dimension(170, 75));
		panel.add(new JLabel("Distance:"));
		outputDistance.setPreferredSize(new Dimension(90, 17));
		outputDistance.setText("0");
		panel.add(outputDistance);
		panel.add(new JLabel("Time(ms):"));
		outputTime.setPreferredSize(new Dimension(80, 17));
		outputTime.setText("0");
		panel.add(outputTime);
		rPanel.add(panel);

		panel = new JPanel();
		panel.setBackground(getBackground());
		panel.setPreferredSize(new Dimension(170, 90));
		panel.setBorder(new TitledBorder("Points"));
		panel.add(newButton);
		panel.add(gridButton);
		panel.add(fromFileButton);
		panel.add(clearButon);
		rPanel.add(panel);

		panel = new JPanel();
		panel.setBackground(getBackground());
		panel.setPreferredSize(new Dimension(170, 180));
		panel.setBorder(new TitledBorder("Methods"));

		int bW = 150;
		int bH = 20;

		nnButton.setPreferredSize(new Dimension(bW, bH));
		panel.add(nnButton);
		rnnButton.setPreferredSize(new Dimension(bW, bH));
		panel.add(rnnButton);
		optButton.setPreferredSize(new Dimension(bW, bH));
		panel.add(optButton);
		gaButton.setPreferredSize(new Dimension(bW, bH));
		panel.add(gaButton);
		gaModButton.setPreferredSize(new Dimension(bW, bH));
		panel.add(gaModButton);
		stopButton.setPreferredSize(new Dimension(bW, bH));
		panel.add(stopButton);
		rPanel.add(panel);

		panel = new JPanel();
		panel.setBackground(getBackground());
		panel.setPreferredSize(new Dimension(170, 150));
		panel.setBorder(new TitledBorder("Best lengths"));
		bestValuesLabel.setPreferredSize(new Dimension(150, 120));
		panel.add(bestValuesLabel);
		rPanel.add(panel);

		this.add(rPanel);
		this.add(new JLabel("TSP Java Implementation - Ramunas Dronga IT-4/1, Ramunas Kraujutis. " +
				"Extended by Tomas Bakutis & Valdemaras Tribockis IT-06/1"));
		this.add(lenLabel);

		newButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(final ActionEvent e)
			{
				doNew();
			}

		});
		gridButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(final ActionEvent e) 
			{
				doGrid();
			}

		});
		nnButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(final ActionEvent e)
			{
				doNearestNeighbour();
			}

		});
		rnnButton.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent e)
			{
				doRNearestNeighbour();
			}
		});
		optButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(final ActionEvent e)
			{
				do2Opt();
			}

		});
		gaButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(final ActionEvent e)
			{
				doGeneticAlgorithm();
			}

		});
		gaModButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				doGeneticAlgorithmModified();
			}

		});
		stopButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e) 
			{
				needToStop = true;
				stopButton.setEnabled(false);
				while (threadWorking) {
					delay.pause(10);
				}
				toggleOperationButtons(!threadWorking);
				stopButton.setEnabled(true);
			}
		});
		
		fromFileButton.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent e)
            {
                doFromFile();
            }

        });
		
		clearButon.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent e)
            {
                doClear();
            }

        });
	}

	public void doNew() 
	{
		if (threadWorking)
		{
			return;
		}
		else 
		{
			bestValues.clear();
			lenLabel.setText("Choose algorithm to solve map...");
			pointsCount = Integer.parseInt(inputPoints.getText());
			if (pointsCount > TSPApplet.MAX_POINTS) {
				pointsCount = TSPApplet.MAX_POINTS;
				inputPoints.setText(Integer.toString(pointsCount));

			}
			map = new TSPMap(pointsCount, display.getWidth(), display.getHeight());
			display.setMap(map);
			return;
		}
	}

	public void doGrid() 
	{
		if (threadWorking)
		{
			return;
		} 
		else 
		{
			bestValues.clear();
			lenLabel.setText("Choose method to solve map...");
			pointsCount = Integer.parseInt(inputPoints.getText());
			map = new TSPMap();
			map.createGridCities(pointsCount, display.getWidth(), display.getHeight());

			display.setMap(map);
			return;
		}
	}
	
	public void doFromFile()
	{
	    if(threadWorking)
	    {
	        return;
	    } 
	    
		JFileChooser fc = new JFileChooser();
		
		CFileFilter fFilter = new CFileFilter();
		
		fc.setFileFilter(fFilter);
		
		fc.setMultiSelectionEnabled(false);
	
		lenLabel.setText("Choose algorithm to solve map...");
	    pointsCount = Integer.parseInt(inputPoints.getText());   
	    
	    if(pointsCount > TSPApplet.MAX_POINTS)
	    {
	    	pointsCount = TSPApplet.MAX_POINTS;
	    	inputPoints.setText(Integer.toString(pointsCount));
	    	
	    }
	    
	    int nCount = 0;
		
		int rc = fc.showDialog(null, "Select XML File");
		
		if (rc == JFileChooser.APPROVE_OPTION)
		{
	    	File file = fc.getSelectedFile();
	
	    	if(file == null)
	    	{
	    		return;
	    	}
	    	
	    	try 
	    	{		        		
	    		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	    		DocumentBuilder db = dbf.newDocumentBuilder();
	    		Document doc = db.parse(file);
	    		doc.getDocumentElement().normalize();
	    		
	    		NodeList nodeLst = doc.getElementsByTagName("dot");
	    		
	    		nCount = nodeLst.getLength();
				
				if( nCount > pointsCount )
				{
					nCount = pointsCount;
				}
				
				CitieData cCData = null;
				
				map = new TSPMap();
				
	    		for (int s = 0; s < nCount; s++) 
	    		{
	        		Node fstNode = nodeLst.item(s);
	        		    
	        		if (fstNode.getNodeType() == Node.ELEMENT_NODE) 
	        		{
	        			cCData = new CitieData();
	        			
	        			Element fstElmnt = (Element) fstNode;
	                    
	                    NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("name");
	                    Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
	                    NodeList fstNm = fstNmElmnt.getChildNodes();
	                    
	                    cCData.m_strCityName = ((Node) fstNm.item(0)).getNodeValue();
	
	                    
	                    NodeList scndNmElmntLst = fstElmnt.getElementsByTagName("x");
	                    Element scndNmElmnt = (Element) scndNmElmntLst.item(0);
	                    NodeList scndNm = scndNmElmnt.getChildNodes();
	                    
	                    cCData.m_ptLoc.x= Integer.parseInt(((Node) scndNm.item(0)).getNodeValue()); // x
	                    
	                    NodeList lstNmElmntLst = fstElmnt.getElementsByTagName("y");
	                    Element lstNmElmnt = (Element) lstNmElmntLst.item(0);
	                    NodeList lstNm = lstNmElmnt.getChildNodes();
	
	                    cCData.m_ptLoc.y= Integer.parseInt(((Node) lstNm.item(0)).getNodeValue()); // y
					  	
					  	map.AddCity(cCData);
	        		}
	    		}
	    		
	    		bestValues.clear();
	            map.createFromFileCities();
	            display.setMap(map);
			} 
	    	catch (Exception e) 
			{
				 e.printStackTrace();
			}
	    }
	}
	
	public void doClear()
	{
		if (threadWorking)
		{
			return;
		} 
		
		bestValues.clear();
		map = new TSPMap();
		display.setMap(map);
	}

	public void doRNearestNeighbour()
	{
		if (threadWorking || map == null)
		{
			return;
		} 
		else 
		{
			worker = new Thread()
			{
				public void run()
				{
					clearBestTour("NNR-" + getDegree());
					toggleOperationButtons(!threadWorking);
					iterationCount = Integer.parseInt(inputIterations.getText());
					ArrayList<NearestNeigbourRandomizedSolver> solvers = new ArrayList<NearestNeigbourRandomizedSolver>();
					for (int i = 0; i < PROCESSOR_COUNT; i++)
					{
						solvers.add(new NearestNeigbourRandomizedSolver(self, map, (int) Math.round(Math.ceil(iterationCount / PROCESSOR_COUNT))));
						solvers.get(solvers.size() - 1).start();
					}
					long iter;
					boolean allFinished;
					do
					{
						iter = 0;
						allFinished = true;
						for (NearestNeigbourRandomizedSolver solver : solvers)
						{
							if (solver.isAlive())
							{
								allFinished = false;
							}
							iter += solver.getIteration();
						}
						lenLabel.setText("Calculating (" + iter + ")");
						delay.pause(100);
					} while (!allFinished);
					
					lenLabel.setText("NNR finished. Best length: " + bestTour.getLength());
					displayTourInfo();
					threadWorking = false;
					toggleOperationButtons(!threadWorking);
				}
			};
			threadWorking = true;
			toggleOperationButtons(!threadWorking);
			worker.start();
		}
	}

	public void doNearestNeighbour()
	{
		if (threadWorking || map == null)
		{
			return;
		} 
		else 
		{
			worker = new Thread()
			{
				public void run() 
				{
					clearBestTour("NN");
					NearestNeigbourSolver tsp = new NearestNeigbourSolver(self, map);
					tsp.start();
					while (tsp.isAlive()) {
						lenLabel.setText("Calculating " + tsp.getIteration());
						delay.pause(10);
					}
					lenLabel.setText("NN done: " + bestTour.getLength());
					displayTourInfo();
					threadWorking = false;
					toggleOperationButtons(!threadWorking);
				}
			};
			
			threadWorking = true;
			toggleOperationButtons(!threadWorking);
			worker.start();
		}
	}

	public void do2Opt() 
	{
		if (threadWorking || map == null)
		{
			return;
		}
		else 
		{
			worker = new Thread() 
			{
				public void run()
				{
					clearBestTour("2-opt");
					iterationCount = Integer.parseInt(inputIterations.getText());
					Tour tour = Tour.getRandomTour(map);
					for (int i = 1; !needStop() && i <= iterationCount; i++) {
						tour.randomize();
						tour.do2Opt();
						addTour(tour);
						lenLabel.setText("Calculating (" + i + ")");
						delay.pause(10);
					}
					lenLabel.setText("2-opt done: " + bestTour.getLength());
					displayTourInfo();
					threadWorking = false;
					toggleOperationButtons(!threadWorking);
				}
			};
			threadWorking = true;
			toggleOperationButtons(!threadWorking);
			worker.start();
		}
	}

	public void doGeneticAlgorithm()
	{
		if (map == null)
			return;
		if (!threadWorking)
		{
			worker = new Thread() 
			{
				public void run() 
				{
					clearBestTour("GA");
					iterationCount = Integer.parseInt(inputIterations.getText());
					popCount = Integer.parseInt(inputPop.getText());
					crossFactor = Integer.parseInt(inputCross.getText());
					muteFactor = Integer.parseInt(inputMute.getText());

					final GeneticSolver tsp = new GeneticSolver(map, popCount, crossFactor, muteFactor);
					for (int i = 1; !needStop() && i < iterationCount; i++)
					{
						tsp.doOneGeneration();
						addTour(tsp.getSolution());
						lenLabel.setText("Calculating (" + i + ")");
					}
					lenLabel.setText("GA done: " + bestTour.getLength());
					displayTourInfo();
					threadWorking = false;
					toggleOperationButtons(!threadWorking);
				}

			};
			threadWorking = true;
			toggleOperationButtons(!threadWorking);
			worker.start();
		}
	}

	public void doGeneticAlgorithmModified()
	{
		if (map == null)
			return;
		if (!threadWorking)
		{
			worker = new Thread()
			{
				public void run() 
				{
					clearBestTour("GA-M");
					iterationCount = Integer.parseInt(inputIterations.getText());
					popCount = Integer.parseInt(inputPop.getText());
					crossFactor = Integer.parseInt(inputCross.getText());
					muteFactor = Integer.parseInt(inputMute.getText());
					final GeneticSolver tsp = new GeneticSolver(map, popCount, crossFactor, muteFactor);
					for (int i = 1; !needStop() && i < iterationCount; i++)
					{
						tsp.doOneGenerationModified();
						addTour(tsp.getSolution());
						lenLabel.setText("Calculating (" + i + ")");
					}
					
					lenLabel.setText("GA-M done: " + bestTour.getLength());
					displayTourInfo();
					threadWorking = false;
					toggleOperationButtons(!threadWorking);
				}

			};
			threadWorking = true;
			toggleOperationButtons(!threadWorking);
			worker.start();
		}
	}

	public int getDegree()
	{
		return inputRnnDegree.getValue();
	}

	private boolean betterTour(Tour tour) 
	{
		return tour != null && (bestTour == null || bestTour.getLength() > tour.getLength());
	}

	public void addTour(Tour tour) 
	{
		if (betterTour(tour)) 
		{
			synchronized (this)
			{
				if (betterTour(tour)) 
				{
					bestTour = (Tour) tour.clone();
					bestValues.put(currentTour, bestTour.getLength());
					displayTour(bestTour);
					displayTourInfo();
				}
			}
		}
	}

	public void displayTourInfo() 
	{
		if (bestTour != null)
		{
			outputDistance.setText(String.format("%4.2f", bestTour.getLength()));
			outputTime.setText(String.format("%d", System.currentTimeMillis() - bestTourStarted));
			StringBuilder text = new StringBuilder();
			for (String method : bestValues.keySet())
			{
				text.append(method).append(": ");
				text.append(String.format("%4.2f", bestValues.get(method))).append("\n");
			}
			bestValuesLabel.setText(text.toString());
		}
	}

	public Tour displayTour(Tour tour) 
	{
		display.setTour(bestTour);
		return tour;
	}

	public TourDisplay getTourDisplay() 
	{
		return display;
	}

	public void clearBestTour(String currentTour)
	{
		this.currentTour = currentTour;
		bestTour = null;
		bestTourStarted = System.currentTimeMillis();
		needToStop = false;
		outputDistance.setText("");
		outputTime.setText("");
	}

	public boolean needStop()
	{
		return needToStop;
	}

	@Override
	public void mouseClicked(MouseEvent arg0) 
	{
	
		
	}

	@Override
	public void mouseEntered(MouseEvent arg0) 
	{
		
	}

	@Override
	public void mouseExited(MouseEvent arg0) 
	{
		
	}

	@Override
	public void mousePressed(MouseEvent arg0)
	{
		
	}

	@Override
	public void mouseReleased(MouseEvent arg0) 
	{	
		if(map == null)
		{
			map = new TSPMap();
		}
		
		int x = arg0.getX()-10;
		int y = arg0.getY()-25;
		
		Point[] ptArr  = null;
		Point ptCoords = null;
		
		int nCountOfPts = 0;
		
		ArrayList<Point> arrPoints = null;
		
		boolean bCanRedraw = false;
		
		if(arg0.getButton() == MouseEvent.BUTTON1)
		{
			arrPoints = new ArrayList<Point>();
			
			ptArr = map.getCurrPoints();
			
			nCountOfPts = map.getPointCount();
			
			// copy all current points to an array
			for(int i = 0; i < nCountOfPts; i++)
			{
				ptCoords = ptArr[i];
				
				//if not null - add
				if(ptCoords != null)
				{
					arrPoints.add(ptCoords);
				}
			}
			
			// create our custom point and add it to array
			ptCoords = new Point(x, y);
			
			arrPoints.add(ptCoords);
			
			bCanRedraw = true;
		}
		else
		if(arg0.getButton() == MouseEvent.BUTTON3)
		{	
			arrPoints = new ArrayList<Point>();
			
			ptArr = map.getCurrPoints();
			
			nCountOfPts = map.getPointCount();
			
			// same story...
			for(int i = 0; i < nCountOfPts; i++)
			{
				ptCoords = ptArr[i];
				
				//if not null...
				if(ptCoords != null)
				{
					arrPoints.add(ptCoords);
				}
			}
			
			boolean bFound = false;
			
			for(int i = 0; i < arrPoints.size(); i++)
			{
				int nX = arrPoints.get(i).x;
				int nY = arrPoints.get(i).y;
				
				if( ((nX > x-3 && nX < x+3)) && ((nY > y-3 && nY < y+3)))
				{
					arrPoints.remove(i);
					map.RemoveCitie(i);
					bFound = true;
					break;
				}
			}
			
			if(!bFound && arrPoints.size() >=1 )
			{
				arrPoints.remove(arrPoints.size()-1);
				map.RemoveCitie(arrPoints.size());
			}
			
			bCanRedraw = true;
		}
		
		if(bCanRedraw)
		{
			map.createCustomCities(arrPoints);
			display.setMap(map);
		}
	}
}
