public static Image generateChart(List<Result> results, int width, int height, int xScroll) {
		Collections.sort(results);
		int chartHeight = height-Y_OFFSET*2;
		int chartWidth = width-X_OFFSET;
		
		Image image = new BufferedImage(X_OFFSET+chartWidth, Y_OFFSET*2+chartHeight, BufferedImage.TYPE_INT_ARGB);
		Graphics g = image.getGraphics();
		Graphics2D g2 = (Graphics2D)g;
		
		RenderingHints rh = new RenderingHints(
				RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		g2.setRenderingHints(rh);
		g2.addRenderingHints(new RenderingHints(
				RenderingHints.KEY_TEXT_ANTIALIASING,
				RenderingHints.VALUE_TEXT_ANTIALIAS_ON));
		
		g.setColor(Color.WHITE);
		g.fillRect(X_OFFSET, Y_OFFSET, chartWidth, chartHeight);
		
		List<List<Result>> groupedResults = getGroupedResults(results);
		int maxSelected = getMaxSelected(results);
		int lowerBound = getMinSelected(results)-1;
		if(lowerBound<0) lowerBound=0;
		int range = maxSelected-lowerBound;
		g.setColor(Color.BLACK);
		g.drawLine(X_OFFSET, Y_OFFSET, X_OFFSET, Y_OFFSET+chartHeight);
		g.drawLine(X_OFFSET, Y_OFFSET+chartHeight, X_OFFSET+chartWidth, Y_OFFSET+chartHeight);
		
		String label = maxSelected+"";
		g.drawString(label, (int) (X_OFFSET-g.getFontMetrics().getStringBounds(label, g).getWidth()-LABEL_MARGIN), Y_OFFSET);
		
		label = lowerBound+"";
		g.drawString(label, (int) (X_OFFSET-g.getFontMetrics().getStringBounds(label, g).getWidth()-LABEL_MARGIN), Y_OFFSET+chartHeight);
		
		int currentX = X_OFFSET + MARGIN_BETWEEN_GROUPS- xScroll;
		for(int i=0;i<groupedResults.size();i++) {
			List<Result> elements = groupedResults.get(i);
			int numberOfElements = elements.size();
			g.setColor(Color.BLACK);
			label = elements.get(0).getId().substring(0, elements.get(0).getId().length()-1);
			Rectangle2D bounds= g.getFontMetrics().getStringBounds(label, g);
			int labelX = (int) ((currentX+((numberOfElements*BAR_WIDTH)+(numberOfElements-1)*MARGIN_BETWEEN_BARS)/2)-(bounds.getWidth()/2));
			int labelY = (int) (Y_OFFSET+chartHeight+LABEL_MARGIN/2+bounds.getHeight());
			if(labelX>X_OFFSET)
				g.drawString(label, labelX, labelY);
			//g.setColor(new Color(Color.HSBtoRGB((float)Math.random(), 1, 1)));
			
			int drawCount = 0;
			int firstDrawX = 0;
			for(int j = 0; j<elements.size();j++) {
				int barHeight = (int) (chartHeight * ((double) elements.get(j).getNumberSelected()-lowerBound)/(double) range);
				if(currentX>X_OFFSET) {
					if(elements.get(j).isFeasible()) {
						g.setColor(Color.BLUE);
					} else {
						g.setColor(Color.RED);
					}
					g.fillRect(currentX, Y_OFFSET+chartHeight-barHeight, BAR_WIDTH, barHeight); 
					if(drawCount==0) {
						firstDrawX = currentX;
					}
					drawCount++;
				}
				currentX+=BAR_WIDTH;
				if(j!=elements.size()-1) {
					//if not the last bar
					currentX+=MARGIN_BETWEEN_BARS;
				}
			}
			if(drawCount>0) {
				double avg = calculateAverageSelected(elements);
				g.setColor(Color.BLACK);
				int lineY= (int) (Y_OFFSET+chartHeight-chartHeight*((avg-lowerBound)/(double) range));
				String avgLabel = formatDouble(avg);
				double lblWidth = g.getFontMetrics().getStringBounds(avgLabel, g).getWidth();
				g.drawString(avgLabel, firstDrawX + (currentX-firstDrawX)/2 - (int) (lblWidth/2), Y_OFFSET-LABEL_MARGIN/2);
				g.drawLine(firstDrawX, lineY, currentX, lineY);
			}
			currentX+=MARGIN_BETWEEN_GROUPS;
		}
		double avg = calculateAverageSelected(results);
		int lineY = (int) (chartHeight*(((double) avg-lowerBound)/(double) range));
		g.setColor(Color.GRAY);
		g.drawLine(X_OFFSET-LABEL_MARGIN, Y_OFFSET+chartHeight-lineY, X_OFFSET+chartWidth, Y_OFFSET+chartHeight-lineY);
		label = formatDouble(avg);
		g.drawString(label, (int) (X_OFFSET-g.getFontMetrics().getStringBounds(label, g).getWidth()-LABEL_MARGIN/2), Y_OFFSET+chartHeight-lineY);		
		return image;
	}