Coding club – number guess

I am currently involved with a Coding Club for high schoolers at my kids school. Currently we are using Python. Coding in the browser using: http://www.codeskulptor.org/

Our most recent discussion using a random number guess game.


import random

# Pick a random number
number = random.randint(0, 10)

# Now ask for guesses until the correct guess is made
done = False

while not done:
guess = int(raw_input('What is your guess?'))
print 'You guessed: %d' % guess

if guess < number: print 'Higher!' elif guess > number:
print 'Lower!'
else:
print 'Right!'
done = True

Rails partials are awesome

This is a great blog post on partials.

http://addictedtonew.com/archives/149/a-bit-on-rails-partials/

Partials are so stealth!!

Great Git plugin tutorial for Eclipse

This is a link to remember for usage of EGit in Eclipse: http://www.vogella.com/articles/EclipseGit/article.html

Tablesorter Size Display Plugin

After using the tablesorter Javascript JQuery plugin a number of times, I finally wrote a nifty little widget to get the size of the table once you sort it.
This plugin works with the Bootstrap Tablesorter version.


// Custom Widget to display current list size of the sortable table
$.tablesorter.addWidget({
// give the widget a id
id: "tableRowDisplayCount",
// format is called when the on init and when a sorting has finished
format: function(table) {
var totalRows = table.tBodies[0].rows.length;
var totalRowsHidden = 0;
for (var i=0; i < totalRows; i++) { if (table.tBodies[0].rows[i].style.display === "none") totalRowsHidden++; } var displayText = "(" + (totalRows - totalRowsHidden) + ")"; $('#table_row_display').html(displayText); } });

GVM vs RVM

After not requiring Groovy for a while, I went about installing it today and was directed to GVM. Very interesting and quick to install. But essentially a RVM knockoff for java.

Android handling images and avoiding out of memory errors

Getting the dreaded “out of memory” looms when reading large images as bitmaps. The key is to scale the image to something smaller when reading the image. There are heaps of solutions on Stack Overflow. But here is some quick code:

 


         private Bitmap mBitmap;
	
	/**
	 * Get Bitmap image from the path.
	 * Scale image to RGB_565 and rotate image 90 degrees
	 */
	private void setBitmap(String path) {
		Uri uri = Uri.fromFile(new File(path));
		ContentResolver mContentResolver = getContentResolver();
		InputStream in = null;
		try {
			BitmapFactory.Options o = new BitmapFactory.Options();
			o.inPurgeable = true;
			o.inSampleSize = 1;
			o.inPreferredConfig = Bitmap.Config.RGB_565;
			in = mContentResolver.openInputStream(uri);
			mBitmap = BitmapFactory.decodeStream(in, null, o);
			mBitmap = rotateImage(mBitmap, 90);
			in.close();
		} catch (Exception e) {
			Log.e(TAG, "file " + path + " not found");
		}
	}
        
        public Bitmap rotateImage(Bitmap src, float degree) {
		// create new matrix
		Matrix matrix = new Matrix();
		// setup rotation degree
		matrix.postRotate(degree);
		Bitmap bmp = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
		return bmp;
	}

Now if you are doing testing here is the above approach but enables you to read the file from the “assets” folder.

         private void setBitmapFromAssets(String fileName) {
		try {
			AssetManager am = this.getAssets();
			InputStream in = am.open(fileName);
			BitmapFactory.Options o = new BitmapFactory.Options();
			o.inPurgeable = true;
			o.inSampleSize = 1;
			o.inPreferredConfig = Bitmap.Config.RGB_565;
			mBitmap = BitmapFactory.decodeStream(in, null, o);
			mBitmap = rotateImage(mBitmap, 90);
			in.close();
		} catch (Exception e) {
			Log.e(TAG, "file " + fileName + " not found");
		}
	}

Android enabling zooming and pan on images

Recently, while working on a project, my Android app required to display an image, use pinch zooming and use the double tap gesture to restore the image.

This functionality is quite similar to viewing an image in the Gallery. After much searching on Stack Overflow, I found the following solution and added the double tap gesture code to it.
The code to go into the Activity

Bitmap bm = BitmapFactory.decodeResource(this.getResources(),R.drawable.test_image);
TouchImageView touchImageView = new TouchImageView(this);
touchImageView.setImageBitmap(bm);
touchImageView.setMaxZoom(4f); 
setContentView(touchImageView);

The custom view which enhances the ImageView.

package com.terenceingram.testapplication.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;

public class TouchImageView extends ImageView {

	Matrix matrix = new Matrix();

	// We can be in one of these 3 states
	static final int NONE = 0;
	static final int DRAG = 1;
	static final int ZOOM = 2;
	int mode = NONE;

	// Remember some things for zooming
	PointF last = new PointF();
	PointF start = new PointF();
	float minScale = 1f;
	float maxScale = 3f;
	float[] m;

	float redundantXSpace, redundantYSpace, origRedundantXSpace, origRedundantYSpace;;

	float width, height;
	static final int CLICK = 3;
	static final float SAVE_SCALE = 1f;
	float saveScale = SAVE_SCALE;

	float right, bottom, origWidth, origHeight, bmWidth, bmHeight, origScale, origBottom,origRight;

	ScaleGestureDetector mScaleDetector;
	GestureDetector mGestureDetector;

	Context context;

	public TouchImageView(Context context) {
		super(context);
		super.setClickable(true);
		this.context = context;
		mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());

		matrix.setTranslate(1f, 1f);
		m = new float[9];
		setImageMatrix(matrix);
		setScaleType(ScaleType.MATRIX);

		setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {

				boolean onDoubleTapEvent = mGestureDetector.onTouchEvent(event);
				if (onDoubleTapEvent) {
					// Reset Image to original scale values
					mode = NONE;
					bottom = origBottom;
					right = origRight;
					last = new PointF();
					start = new PointF();
					m = new float[9];
					saveScale = SAVE_SCALE;
					matrix = new Matrix();
					matrix.setScale(origScale, origScale);
					matrix.postTranslate(origRedundantXSpace, origRedundantYSpace);
					setImageMatrix(matrix);
					invalidate();
					return true;
				} 

				mScaleDetector.onTouchEvent(event);

				matrix.getValues(m);
				float x = m[Matrix.MTRANS_X];
				float y = m[Matrix.MTRANS_Y];
				PointF curr = new PointF(event.getX(), event.getY());

				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					last.set(event.getX(), event.getY());
					start.set(last);
					mode = DRAG;
					break;
				case MotionEvent.ACTION_MOVE:
					if (mode == DRAG) {
						float deltaX = curr.x - last.x;
						float deltaY = curr.y - last.y;
						float scaleWidth = Math.round(origWidth * saveScale);
						float scaleHeight = Math.round(origHeight * saveScale);
						if (scaleWidth < width) { 							deltaX = 0; 							if (y + deltaY > 0)
								deltaY = -y;
							else if (y + deltaY < -bottom)
								deltaY = -(y + bottom);
						} else if (scaleHeight < height) { 							deltaY = 0; 							if (x + deltaX > 0)
								deltaX = -x;
							else if (x + deltaX < -right) 								deltaX = -(x + right); 						} else { 							if (x + deltaX > 0)
								deltaX = -x;
							else if (x + deltaX < -right) 								deltaX = -(x + right); 							if (y + deltaY > 0)
								deltaY = -y;
							else if (y + deltaY < -bottom)
								deltaY = -(y + bottom);
						}
						matrix.postTranslate(deltaX, deltaY);
						last.set(curr.x, curr.y);
					}
					break;

				case MotionEvent.ACTION_UP:
					mode = NONE;
					int xDiff = (int) Math.abs(curr.x - start.x);
					int yDiff = (int) Math.abs(curr.y - start.y);
					if (xDiff < CLICK && yDiff < CLICK) 						performClick(); 					break; 				case MotionEvent.ACTION_POINTER_UP: 					mode = NONE; 					break; 				} 				 				setImageMatrix(matrix); 				invalidate(); 				 				return true; // indicate event was handled 			} 		}); 		 		mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { 		    @Override 		    public boolean onDoubleTapEvent(MotionEvent e) { 		        return true; 		    } 		}); 	} 	@Override 	public void setImageBitmap(Bitmap bm) { 		super.setImageBitmap(bm); 		bmWidth = bm.getWidth(); 		bmHeight = bm.getHeight(); 	} 	public void setMaxZoom(float x) { 		maxScale = x; 	} 	private class ScaleListener extends 			ScaleGestureDetector.SimpleOnScaleGestureListener { 		@Override 		public boolean onScaleBegin(ScaleGestureDetector detector) { 			mode = ZOOM; 			return true; 		} 		@Override 		public boolean onScale(ScaleGestureDetector detector) { 			float mScaleFactor = (float) Math.min( 					Math.max(.95f, detector.getScaleFactor()), 1.05); 			float origScale = saveScale; 			saveScale *= mScaleFactor; 			if (saveScale > maxScale) {
				saveScale = maxScale;
				mScaleFactor = maxScale / origScale;
			} else if (saveScale < minScale) {
				saveScale = minScale;
				mScaleFactor = minScale / origScale;
			}
			right = width * saveScale - width
					- (2 * redundantXSpace * saveScale);
			bottom = height * saveScale - height
					- (2 * redundantYSpace * saveScale);
			if (origWidth * saveScale <= width
					|| origHeight * saveScale <= height) {
				matrix.postScale(mScaleFactor, mScaleFactor, width / 2,
						height / 2);
				if (mScaleFactor < 1) {
					matrix.getValues(m);
					float x = m[Matrix.MTRANS_X];
					float y = m[Matrix.MTRANS_Y];
					if (mScaleFactor < 1) {
						if (Math.round(origWidth * saveScale) < width) {
							if (y < -bottom) 								matrix.postTranslate(0, -(y + bottom)); 							else if (y > 0)
								matrix.postTranslate(0, -y);
						} else {
							if (x < -right) 								matrix.postTranslate(-(x + right), 0); 							else if (x > 0)
								matrix.postTranslate(-x, 0);
						}
					}
				}
			} else {
				matrix.postScale(mScaleFactor, mScaleFactor,
						detector.getFocusX(), detector.getFocusY());
				matrix.getValues(m);
				float x = m[Matrix.MTRANS_X];
				float y = m[Matrix.MTRANS_Y];
				if (mScaleFactor < 1) {
					if (x < -right) 						matrix.postTranslate(-(x + right), 0); 					else if (x > 0)
						matrix.postTranslate(-x, 0);
					if (y < -bottom) 						matrix.postTranslate(0, -(y + bottom)); 					else if (y > 0)
						matrix.postTranslate(0, -y);
				}
			}
			return true;

		}
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		width = MeasureSpec.getSize(widthMeasureSpec);
		height = MeasureSpec.getSize(heightMeasureSpec);
		// Fit to screen.
		float scale;
		float scaleX = (float) width / (float) bmWidth;
		float scaleY = (float) height / (float) bmHeight;
		scale = Math.min(scaleX, scaleY);
		matrix.setScale(scale, scale);
		setImageMatrix(matrix);
		saveScale = SAVE_SCALE;
		origScale = scale;

		// Center the image
		redundantYSpace = (float) height - (scale * (float) bmHeight);
		redundantXSpace = (float) width - (scale * (float) bmWidth);
		redundantYSpace /= (float) 2;
		redundantXSpace /= (float) 2;

		origRedundantXSpace = redundantXSpace;
		origRedundantYSpace = redundantYSpace;

		matrix.postTranslate(redundantXSpace, redundantYSpace);

		origWidth = width - 2 * redundantXSpace;
		origHeight = height - 2 * redundantYSpace;
		right = width * saveScale - width - (2 * redundantXSpace * saveScale);
		bottom = height * saveScale - height
				- (2 * redundantYSpace * saveScale);
		origRight = right;
		origBottom = bottom;
		setImageMatrix(matrix);
	}

}

Eclipse display worskspace location

Recently, whilst using eclipse I needed to switch to different workspace so that I could use a different branch of the code I had been working. In order to eliminate confusion as to which code I was working on:

  • I created a new workspace for this branch under File/ Switch Workspace
  • Amended the eclipse startup to include the “-showlocation” switch

So now I have two workspaces and the location of the workspace is displayed in the title bar so I don’t get confused as to which branch I am working on.

Useful VI commands

Show line numbers
:set number

Replacing a text within a file in place

Recently I had to replace some text within a file, I also wanted this to occur in place. I ended up with two solutions. Mainly because of the Solaris version. But also because I wanted to play with Groovy again.

1. Perl on the commandline

perl -pi -e 's/1.2-SNAPSHOT/1.2/g' pom.xml

2. Using Groovy
Refer to Groovy: Writing to a File