Friday, May 24, 2013

Another simple Python game: Memory

This week's assignment is a simple and straight forward Memory game. You play with a set of cards facedown and you are allowed to flip and view two cards in one turn and if they both match, they remain opened. If they don't they go back to facedown mode and you use your memory to match the cards. You can play it here:

UPDATE: I was doing peer evaluation for this and I found one implementation which is better than mine. It uses classes. Check it here:

__author__ = 'RK Kuppala'
# implementation of card game - Memory
import simplegui
import random

num_list = []
exposed = []
state = 0
first_pick = 0
second_pick = 0
moves = 0

# helper function to initialize globals
def init():
    global num_list, exposed, moves
    moves = 0
    num_list = [i%8 for i in range(16)]
    random.shuffle(num_list)
    exposed = [False for i in range(16)]
    pass


# define event handlers
def mouseclick(pos):
    global state, first_pick, second_pick, moves
    this_pick = int(pos[0] / 50)
    if state == 0:
        first_pick = this_pick
        exposed[first_pick] = True
        state = 1
        moves += 1
    elif state == 1:
        if not exposed[this_pick]:
            second_pick = int(pos[0] / 50)
            exposed[second_pick] = True
            state = 2
            moves += 1
    elif state == 2:
        if not exposed[this_pick]:
            if num_list[first_pick] == num_list[second_pick]:
                pass
            else:
                exposed[first_pick] = False
                exposed[second_pick] = False
            first_pick = this_pick
            exposed[first_pick] = True
            state = 1
            moves += 1
    l.set_text("Moves = " + str(moves))
    pass


# cards are logically 50x100 pixels in size
def draw(canvas):
    offset = 50
    hor_pos = -25
    for i in range(len(num_list)):
        hor_pos += offset
        canvas.draw_text(str(num_list[i]), [hor_pos, 50], 30, "White")
    exposed_pos = -50
    for i in exposed:
        exposed_pos += offset
        if not i:
            canvas.draw_polygon([(exposed_pos, 0), (exposed_pos + 50, 0), (exposed_pos + 50, 100), (exposed_pos + 0, 100)], 10, "White", "Orange")

# create frame and add a button and labels
frame = simplegui.create_frame("Memory", 800, 100)
frame.add_button("Restart", init)
l=frame.add_label("Moves = 0")

# initialize global variables
init()

# register event handlers
frame.set_mouseclick_handler(mouseclick)
frame.set_draw_handler(draw)

# get things rolling
frame.start()

Saturday, May 18, 2013

Simple Python Game: Pong

Here goes this week's game. The classic Pong game. You can play this game on your browser here (don't try this on IE). Its a two player game. Player 1 can use 'w' and 's' keys and Player 2 can use ↑ and ↓. I would like to make this game working locally on Windows using tkinter. Let see

# Author: RK

import simplegui
import random

# initialize globals - pos and vel encode vertical info for paddles
WIDTH = 600
HEIGHT = 400       
BALL_RADIUS = 20
PAD_WIDTH = 8
PAD_HEIGHT = 80
HALF_PAD_WIDTH = PAD_WIDTH / 2
HALF_PAD_HEIGHT = PAD_HEIGHT / 2

ball_pos = [WIDTH/2, HEIGHT/2]
ball_vel = [-random.randrange(60, 180) / 60, random.randrange(120, 240) / 60]
paddle1_pos = HEIGHT/2
paddle2_pos = HEIGHT/2

# helper function that spawns a ball by updating the 
# ball's position vector and velocity vector
# if right is True, the ball's velocity is upper right, else upper left
def ball_init(right):
    global ball_pos, ball_vel # these are vectors stored as lists
    ball_pos = [WIDTH/2,HEIGHT/2]
    ball_vel[1] = -random.randrange(60, 180)/60
    if right == True:
        ball_vel[0] = random.randrange(120, 240)/60
    else:
        ball_vel[0] = -random.randrange(120, 240)/60
    pass

def new_game():
    global paddle1_pos, paddle2_pos, paddle1_vel, paddle2_vel
    global score1, score2
    paddle1_pos = HEIGHT/2
    paddle2_pos = HEIGHT/2
    paddle1_vel = 0
    paddle2_vel = 0
    score1 = 0
    score2 = 0
    ball_init(0 == random.randrange(0, 11) % 2)
    pass 

# define event handlers


def draw(c):
    global score1, score2, paddle1_pos, paddle2_pos, paddle1_vel, paddle2_vel, ball_pos, ball_vel
    # update paddle's vertical position, keep paddle on the screen
    if paddle1_pos < (HALF_PAD_HEIGHT) and paddle1_vel < 0:
        paddle_vel = 0
    if paddle2_pos < (HALF_PAD_HEIGHT) and paddle2_vel < 0:
        paddle2_vel = 0
    if paddle1_pos > (HEIGHT - (HALF_PAD_HEIGHT)) and paddle1_vel >0:
        paddle2_vel = 0
    if paddle2_pos > (HEIGHT - (HALF_PAD_HEIGHT)) and paddle2_vel > 0:
        paddle2_vel = 0
    paddle1_pos += paddle1_vel
    paddle2_pos += paddle2_vel
    # draw mid line and gutters
    c.draw_line([WIDTH / 2, 0],[WIDTH / 2, HEIGHT], 1, "White")
    c.draw_line([PAD_WIDTH, 0],[PAD_WIDTH, HEIGHT], 1, "White")
    c.draw_line([WIDTH - PAD_WIDTH, 0],[WIDTH - PAD_WIDTH, HEIGHT], 1, "White")
    # draw paddles
    c.draw_polygon([(0, paddle1_pos-HALF_PAD_HEIGHT), (0, paddle1_pos+HALF_PAD_HEIGHT), (PAD_WIDTH-2, paddle1_pos+HALF_PAD_HEIGHT),(PAD_WIDTH-2,paddle1_pos-HALF_PAD_HEIGHT)], PAD_WIDTH-1, "White","White")
    c.draw_polygon([(WIDTH, paddle2_pos-HALF_PAD_HEIGHT), (WIDTH, paddle2_pos+HALF_PAD_HEIGHT), (WIDTH-PAD_WIDTH+2, paddle2_pos+HALF_PAD_HEIGHT),(WIDTH-PAD_WIDTH+2,paddle2_pos-HALF_PAD_HEIGHT)], PAD_WIDTH-1, "White","White") 
    # update ball
    ball_pos[0] += ball_vel[0]
    ball_pos[1] += ball_vel[1]
    if ball_pos[1] >= (HEIGHT - BALL_RADIUS) or ball_pos[1] <= (BALL_RADIUS):
        ball_vel[1] = -ball_vel[1]
    if ball_pos[0] <= (PAD_WIDTH + BALL_RADIUS):
        if ball_pos[1] < (paddle1_pos - HALF_PAD_HEIGHT) or ball_pos[1] > (paddle1_pos + HALF_PAD_HEIGHT):
            ball_init(True)
            score2 += 1
        else:
            ball_vel[0] = -ball_vel[0] * 1.1
            
    if  ball_pos[0] >= (WIDTH - PAD_WIDTH - BALL_RADIUS):
        if ball_pos[1] < (paddle2_pos - HALF_PAD_HEIGHT) or ball_pos[1] > (paddle2_pos + HALF_PAD_HEIGHT):
            ball_init(False)
            score1 += 1
        else:
            ball_vel[0] = -ball_vel[0] * 1.1        
    # draw ball and scores
    c.draw_circle(ball_pos, BALL_RADIUS, 2, "Yellow", "White")
    c.draw_text(str(score1), (170, 50), 36, "Yellow")
    c.draw_text(str(score2), (400, 50), 36, "Yellow")
    
def keydown(key):
    global paddle1_vel, paddle2_vel
    if key == simplegui.KEY_MAP['w']:
        paddle1_vel = -4
    elif key == simplegui.KEY_MAP['s']:
        paddle1_vel = 4
    elif key == simplegui.KEY_MAP['up']:
        paddle2_vel = -4
    elif key == simplegui.KEY_MAP['down']:
        paddle2_vel = 4
        
def keyup(key):
    global paddle1_vel, paddle2_vel
    if key == simplegui.KEY_MAP['w']:
        paddle1_vel = 0
    elif key == simplegui.KEY_MAP['s']:
        paddle1_vel = 0
    elif key == simplegui.KEY_MAP['up']:
        paddle2_vel = 0
    elif key == simplegui.KEY_MAP['down']:
        paddle2_vel = 0

# create frame
frame = simplegui.create_frame("Pong", WIDTH, HEIGHT)
frame.set_draw_handler(draw)
frame.set_keydown_handler(keydown)
frame.set_keyup_handler(keyup)

# start frame
frame.start()
new_game()

Thursday, May 16, 2013

Step By Step: SQL Server 2012 AlwaysOn Availability Groups Lab Setup Using VirtualBox

I was inspired to write this post by the super awesome DBA, Jonathan Kehayias of sqlskills. He has a great series of articles on setting up a home lab using virtualbox and evaluation software from Microsoft available as free downloads. Check out his articles on sqlskills.

If you are on this page and reading this, chances are that you already know what AlwaysOn is so I am not going to explain it again.For a quick overview of this new High availability/disaster recovery solution, go read this article. Now lets get started with building our lab.

What do you need?

In order to follow this tutorial, you need the following

The latest version of VirtualBox
Windows server 2008 R2 with sp1, evaluation edition
SQL Server 2012 Evaluation edition

Coming to the hardware, you need a decent laptop/desktop with 8 GB RAM and a good processor (may be core i5). You can try with lesser RAM too, but things will be a little slow. You need at least 4 VMs to test a basic setup of AlwaysOn. The server that acts as a domain controller can not be a part of availability groups. Don't worry about storage for all these VMs, because we are going to use linked clones that make use of resources from a base VM.

Saturday, May 11, 2013

A not so exciting game in Python: Stop Watch

Another week and another assignment. The game itself is not very exciting. You can start and stop the timer, every start is an attempt and every stop exactly at 0 is a win.

Thursday, May 9, 2013

Visual Fox Pro Hell: fpt file missing or invalid (memo file corruption)

I know, its 2013 and nobody should be dealing with Visual Fox Pro 6.0 databases, but one of the clients I support has a legacy system that uses foxpro databases. We have an SSIS job that pulls data everyday from `foxpro` and it recently started failing with the error, `person.fpt is missing or invalid`, I initially thought it was a network issue but the frequency of the failure increased and one fine day it stopped working at all. Lesson - don't wait for it to break completely. Because some day it will. So I naturally started googling and that was a time travel back to the ancient kingdoms of the internet. Microsoft's resources didn't help much, and I had to deal with shareware, freeware software that promise `.dbf` and `.fpt` repair as soon as you pay, help forums with no answers and annoying browser addons etc. After trying a lot of demo software I thought may be its just the `.fpt` file that needs rebuilding. So going though the documentation I thought I'd make a copy of this database and see if it rebuilds `.fpt` file and fortunately, it worked!

Wednesday, May 1, 2013

Game: Guess the number!

I have recently started learning Python from an online course and we had this course assignment to program this game. I am avoiding the name of the course and the name of the online resource on purpose because I don't want this show up on Google results. I'm just childishly happy that I wrote something and I wanted to save it here. This code may not work as is, because it uses some modules that are not part of standard python installations. After writing it in Python, I tried to do it on Powershell too and it kind of worked.

Thursday, April 25, 2013

Zen of Python

I just saw this on Python.org and I loved it so much I have to save it on my blog. It applies not just for Python but programming in general:

    Beautiful is better than ugly.
    Explicit is better than implicit.
    Simple is better than complex.
    Complex is better than complicated.
    Flat is better than nested.
    Sparse is better than dense.
    Readability counts.
    Special cases aren't special enough to break the rules.
    Although practicality beats purity.
    Errors should never pass silently.
    Unless explicitly silenced.
    In the face of ambiguity, refuse the temptation to guess.
    There should be one-- and preferably only one --obvious way to do it.
    Although that way may not be obvious at first unless you're Dutch.
    Now is better than never.
    Although never is often better than *right* now.
    If the implementation is hard to explain, it's a bad idea.
    If the implementation is easy to explain, it may be a good idea.
    Namespaces are one honking great idea -- let's do more of those!
                                                -- Tim Peters

Tuesday, April 23, 2013

Run VirtualBox VMs in the background - headless mode using VboxManage

I love virtualbox for my virtualization needs for its ease of use and low resource utilization. I have a bunch of VMs created to install and test SQL Server high availability features like AlwaysOn, Clustering etc. Working with these VMs I always wished if there was a way to just run these VMs in the background instead of keeping a window open for each VM. I googled around a bit and it is possible to start a VM in background mode, in virtualbox speak, its called headless mode.

Escaping wildcards while using LIKE predicate

When you look up the LIKE predicate on BOL you'll see the wildcard characters like %, _,[], [^] that will help finding a pattern in your tables. For example, the below sql will give you students whose lastname starts with D.

SELECT firstname, lastname
FROM students
WHERE lastname LIKE 'D%'

But things start getting interesting when your data has one or all of the above wildcards in your data and you would like to lookup a pattern. Lets create a table to illustrate this:

CREATE TABLE wildcards
(
  c1 int identity,
  c2 nvarchar(20)
);
--insert some data that has wildcards

INSERT INTO wildcards VALUES ('Joker')
INSERT INTO wildcards VALUES ('_Joker')
INSERT INTO wildcards VALUES ('Joker_')
INSERT INTO wildcards VALUES ('%Joker')
INSERT INTO wildcards VALUES ('%%Joker')
INSERT INTO wildcards VALUES ('[]Joker')
INSERT INTO wildcards VALUES ('[][]Joker')
INSERT INTO wildcards VALUES ('[^]Joker')
INSERT INTO wildcards VALUES ('__Joker')
GO
--check data,

SELECT * FROM wildcards

--9 rows

Now try a regular query with Like predicate and try to find all jokers that have an underscore preceding the value.

SELECT * FROM wildcards WHERE c2 LIKE '_%'

Surprise! SQL server returns all 9 rows. It thinks that we passed two wildcards. We need to tell SQL Server not to treat '_' as wildcard. You can do so using the ESCAPE keyword.

SELECT * FROM wildcards WHERE c2 LIKE '!_%' ESCAPE '!'
SELECT * FROM wildcards WHERE c2 LIKE '%!_' ESCAPE '!'


Monday, April 22, 2013

Scheduling SQL Profiler trace as SQL Agent job

Connect to the server using management studio and go to Tools and Launch SQL Server Profiler.
Connect to the server you want to run the trace on.