# Blackjack __author__ = 'RK' import simplegui import random CARD_SIZE = (73, 98) CARD_CENTER = (36.5, 49) card_images = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/cards.jfitz.png") CARD_BACK_SIZE = (71, 96) CARD_BACK_CENTER = (35.5, 48) card_back = simplegui.load_image("https://www.dropbox.com/s/75fcadgeewharzg/joker.jpg?dl=1") # initialize some useful global variables in_play = False outcome = "" score = 0 # define globals for cards SUITS = ('C', 'S', 'H', 'D') RANKS = ('A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K') VALUES = {'A':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':10, 'Q':10, 'K':10} # define card class class Card: def __init__(self, suit, rank): if (suit in SUITS) and (rank in RANKS): self.suit = suit self.rank = rank else: self.suit = None self.rank = None print "Invalid card: ", suit, rank def __str__(self): return self.suit + self.rank def get_suit(self): return self.suit def get_rank(self): return self.rank def draw(self, canvas, pos): card_loc = (CARD_CENTER[0] + CARD_SIZE[0] * RANKS.index(self.rank), CARD_CENTER[1] + CARD_SIZE[1] * SUITS.index(self.suit)) canvas.draw_image(card_images, card_loc, CARD_SIZE, [pos[0] + CARD_CENTER[0], pos[1] + CARD_CENTER[1]], CARD_SIZE) # define hand class class Hand: def __init__(self): self.hand = [] def __str__(self): s = '' for c in self.hand: s += str(c) s += " " return s def add_card(self, card): self.hand.append(card) def hit(self,deck): self.add_card(deck.deal_card()) player.get_value() dealer.get_value() def get_value(self): """ count aces as 1, if the hand has an ace, then add 10 to hand value if it doesn't bust""" global in_play, message, score self.value = 0 A = 0 for card in self.hand: if card[1] == 'A': A += 1 self.value += VALUES[card[1]] if A > 0 and self.value < 12: self.value += 10 if self.value > 21: if in_play and (player.value > 21): message = "You lose! The computer wins!" score -= 1 in_play = False return self.value def draw(self, canvas, pos): """draw a hand on the canvas, use the draw method for cards""" x = 0 for card in self.hand: card = Card(self.hand[x][0], self.hand[x][1]) card.draw(canvas, [x * 90 + 50, pos * 200]) x += 1 # define deck class class Deck: def __init__(self): self.deck = [(suit, rank) for suit in SUITS for rank in RANKS] self.shuffle() def shuffle(self): random.shuffle(self.deck) def deal_card(self): return self.deck.pop() #define event handlers for buttons def deal(): global outcome, in_play,deck, hand, dealer, hand_total, player, message, score message = "Do you choose to Hit or Stand?" if in_play: score -= 1 message = "That's cheating!" hand_total = 0 deck = Deck() player = Hand() dealer = Hand() player.hit(deck) player.hit(deck) dealer.hit(deck) dealer.hit(deck) in_play = True def hit(): global player, in_play, message """if the hand is in play, hit the player""" player.get_value() if (player.value <= 21) and in_play: player.hit(deck) if player.value < 21: message = "OK. Do you want to Hit again or Stand?" """if busted, assign a message to outcome, update in_play and score""" else: message = "STOP. CLICKING. THAT." def stand(): global value, message, in_play, score if in_play == False: message = "STOP. CLICKING. THAT." else: player.value message = "Please wait! Computer is making its move..." timer.start() in_play = False def dealercard(): global score, message if dealer.value < 17: dealer.hit(deck) elif (player.value > dealer.value) or (dealer.value > 21): message = "You win. Congrats! Deal again?" score += 1 timer.stop() else: message = "Computer Wins. Deal again?" score -= 1 timer.stop() # draw handler def draw(canvas): global dealer, player, message, in_play, score scorestring = "Your points are: " scorestring += str(score) dealer.draw(canvas, 1) player.draw(canvas, 2) canvas.draw_text(message, [50, 185], 18, "Black") canvas.draw_text(scorestring, [480, 555], 14, "Yellow") canvas.draw_text("BlackJack Game", [480, 585], 18, "Black") if in_play: canvas.draw_image(card_back, CARD_BACK_CENTER, CARD_BACK_SIZE, (88, 249), (70, 94)) # initialization frame frame = simplegui.create_frame("Blackjack", 600, 600) frame.set_canvas_background("Gray") timer = simplegui.create_timer(1000, dealercard) #create buttons and canvas callback frame.add_button("Deal", deal, 200) frame.add_button("Hit", hit, 200) frame.add_button("Stand", stand, 200) frame.set_draw_handler(draw) # get things rolling frame.start() deck = Deck() player = Hand() dealer = Hand() message = "BlackJack Game. Please hit Deal"
Friday, May 31, 2013
Python Game: Blackjack
This week's game is Blackjack. Go play it here
Thursday, May 30, 2013
A simple list manipulation - Computing primes using Sieve of Eratosthenes process
I am incredibly dumb that I had to wrestle with this problem for a long time before being able to solve it. But the experience has been invaluable.
The Problem:
Initialize n to be 1000. Initialize numbers to be a list of numbers from 2 to n, but not including n. With results starting as the empty list, repeat the following as long as numbers contains any numbers.
1. Add the first number in numbers to the end of results.
2. Remove every number in numbers that is evenly divisible by (has no remainder when divided by) the number that you
had just added to results.
How long is results?
The Solution (It is ugly!)
It looks like this computes the primes less than n, by a process known as Sieve of Eratosthenes. Below is another, more elegant and pythonic way to do it.
I was stuck with infinite loops with my original program before I stumbled upon pythontutor.org and saw the execution step by step. Below is the visualized execution of my program.
The Problem:
Initialize n to be 1000. Initialize numbers to be a list of numbers from 2 to n, but not including n. With results starting as the empty list, repeat the following as long as numbers contains any numbers.
1. Add the first number in numbers to the end of results.
2. Remove every number in numbers that is evenly divisible by (has no remainder when divided by) the number that you
had just added to results.
How long is results?
The Solution (It is ugly!)
n = 1000 numbers = range(2, n) results = [] while numbers: i = numbers[0] results.append(i) for number in numbers: if number % i == 0: numbers.remove(number) print numbers print len(results)
It looks like this computes the primes less than n, by a process known as Sieve of Eratosthenes. Below is another, more elegant and pythonic way to do it.
n = 1000 numbers = range(2, n) results = [] while numbers != []: results.append(numbers[0]) numbers = [n for n in numbers if n % numbers[0] != 0] print len(results)
I was stuck with infinite loops with my original program before I stumbled upon pythontutor.org and saw the execution step by step. Below is the visualized execution of my program.
SQL Server: Storage internals, recovery model and log behavior
This is not a comprehensive post on SQL Server storage and internals, but we recently ran into an interesting issue. We were doing PCI scans on some of our servers for PCI compliance. There is a tool that scans each bit and byte inside the database and server and return a list of possible violations. Our developers identified data that needs to be removed in some legacy systems and they cleaned up the data by updating offending fields with blank values, deleting some tables altogether etc. But the scan tool would often find violations even after truncating/deleting data. Some of those databases were on simple and some were in FULL recovery mode and I had to explain how log backups, recovery and checkpoint affect the databases and I came up with this small tutorial.
Lets create a database to play with. Lets set that database in FULL recovery mode and create some data and see whats in the log.
A database with no data in it is no good. Lets create a table and see. I am going to define DEFAULTS just to save some time and effort while inserting records into that table. I'm just lazy:
A full backup initiates an LSN chain, so lets do a FULL backup.
Lets check and try to find more details about our transaction log. There is a very useful DBCC command, LOGINFO which allows us to do that. Here is Paul Randal demonstrating the circular nature of the log using DBCC LOGINFO.
You should see some thing similar to the below image.
So there are a couple of VLFs (Virtual Log Files) and on one of them, the status is 2, which means 'Active'. Can we find more information? What is in those log files? Yes we can, using the undocumented function fn_dblog
This will return a lot of data which may not make much sense to you at first. That's ok. We just created a table and there is no data in it. Let us insert some data and see how the log behaves.
How does out VLF files look now?
Our VLF count has increased and now two VLFs are marked as Active. Let us insert some more records and see what happens to the log
Since we seem to have a lot of data, may be try and read the log and see if we can make sense of the output from fn_dlog function output. Lets use the query we used above, but only this time, we know we only ever dealt with the CreditInfo table. So lets narrow the scope of the results based on this.
You'll notice the details of the operation we performed, LOP_INSERT_ROWS. So is that the actual data? Yes and no. Its not actual data in the sense of data in a data file. It is knowledge about what happened to that data for SQL Server's use. I had to demonstrate this to our devs because they were claiming that there is credit card info in the log files as per the scanning tool.
Coming back to log, observe how the log file grows and how most of the VLFs are in Active mode. This means they are currently being used and are not marked for reuse yet. We obviously dont want our log file to grow indefinitely. It needs to be cleared, right? So what clears a transaction log file when the database is in Full Recovery Mode? Two things- First, When a checkpoint has occurs since the last full backup AND a transaction log backup. Lets issue a manual CHECKPOINT and do a log backup and see what happens to our log.
What happened? All the VLFs are still there, but the log backup has cleared the transaction log and the existing virtual log files are marked as inactive. So they can be used again for any transactions in future. Now, try to read the log again and limit your scope to CreditInfo table.
Boom! there is nothing related to CreditInfo object. Didn't I tell you that the log backup cleared the transaction log?
But you can see that data in the data file. Use a simple select.
Ok, this is credit card data and one internet kitten will die for each row you keep in your database. Its vile. So lets get rid of it. After you truncate the table, will you find any information about it in the log file? Yes, you will. You'll see LOP_MODIFY_ROW operation.
The credit card scan utility still sees the data, we just truncated the table and still. Ok, lets do a log backup.
Read the log again
Still see the records? How about a checkpoint
At this point, if you try to read again, you wont see any records related to CreditInfo and its completely gone. I was able to explain about FULL Recovery mode, nature of log using this example to our devs and I hope you find it useful too.
Lets create a database to play with. Lets set that database in FULL recovery mode and create some data and see whats in the log.
CREATE DATABASE storagefun; GO ALTER DATABASE storagefun SET RECOVERY FULL GO
A database with no data in it is no good. Lets create a table and see. I am going to define DEFAULTS just to save some time and effort while inserting records into that table. I'm just lazy:
USE storagefun GO CREATE TABLE CreditInfo ( id int identity, name nvarchar(30) DEFAULT 'SQL Server is fun!', ccnumber nvarchar(40) DEFAULT '1234-4567-7891-1023' )
A full backup initiates an LSN chain, so lets do a FULL backup.
BACKUP DATABASE storagefun TO DISK = 'D:\SQLData\Backups\Storagefun.bak'
Lets check and try to find more details about our transaction log. There is a very useful DBCC command, LOGINFO which allows us to do that. Here is Paul Randal demonstrating the circular nature of the log using DBCC LOGINFO.
DBCC LOGINFO GO
You should see some thing similar to the below image.
So there are a couple of VLFs (Virtual Log Files) and on one of them, the status is 2, which means 'Active'. Can we find more information? What is in those log files? Yes we can, using the undocumented function fn_dblog
SELECT [Previous LSN] , [Current LSN] , [Transaction ID] , [Operation], [CONTEXT], [AllocUnitName] , [Page ID], [Slot ID], [Offset in Row] , [Transaction Name] , [Begin Time], [End Time], [Number of Locks] , [Lock Information] , [RowLog Contents 0] , [RowLog Contents 1] , [RowLog Contents 2] , [RowLog Contents 3] , [RowLog Contents 4] , [Log Record], [Log Record Fixed Length] , [Log Record Length] FROM fn_dblog (null,null) GO
This will return a lot of data which may not make much sense to you at first. That's ok. We just created a table and there is no data in it. Let us insert some data and see how the log behaves.
INSERT INTO CreditInfo VALUES ( DEFAULT, DEFAULT); GO 200
How does out VLF files look now?
DBCC LOGINFO GO
Our VLF count has increased and now two VLFs are marked as Active. Let us insert some more records and see what happens to the log
INSERT INTO CreditInfo VALUES ( DEFAULT, DEFAULT); GO 5000 DBCC LOGINFO GO
Since we seem to have a lot of data, may be try and read the log and see if we can make sense of the output from fn_dlog function output. Lets use the query we used above, but only this time, we know we only ever dealt with the CreditInfo table. So lets narrow the scope of the results based on this.
SELECT [Previous LSN] , [Current LSN] , [Transaction ID] , [Operation], [CONTEXT], [AllocUnitName] , [Page ID], [Slot ID], [Offset in Row] , [Transaction Name] , [Begin Time], [End Time], [Number of Locks] , [Lock Information] , [RowLog Contents 0] , [RowLog Contents 1] , [RowLog Contents 2] , [RowLog Contents 3] , [RowLog Contents 4] , [Log Record], [Log Record Fixed Length] , [Log Record Length] FROM fn_dblog (null,null)WHERE AllocUnitName LIKE '%CreditInfo%'
You'll notice the details of the operation we performed, LOP_INSERT_ROWS. So is that the actual data? Yes and no. Its not actual data in the sense of data in a data file. It is knowledge about what happened to that data for SQL Server's use. I had to demonstrate this to our devs because they were claiming that there is credit card info in the log files as per the scanning tool.
Coming back to log, observe how the log file grows and how most of the VLFs are in Active mode. This means they are currently being used and are not marked for reuse yet. We obviously dont want our log file to grow indefinitely. It needs to be cleared, right? So what clears a transaction log file when the database is in Full Recovery Mode? Two things- First, When a checkpoint has occurs since the last full backup AND a transaction log backup. Lets issue a manual CHECKPOINT and do a log backup and see what happens to our log.
CHECKPOINT GO BACKUP LOG storagefun TO DISK = 'D:\SQLData\storagefun_log.trn' GO
What happened? All the VLFs are still there, but the log backup has cleared the transaction log and the existing virtual log files are marked as inactive. So they can be used again for any transactions in future. Now, try to read the log again and limit your scope to CreditInfo table.
SELECT [Previous LSN] , [Current LSN] , [Transaction ID] , [Operation], [CONTEXT], [AllocUnitName] , [Page ID], [Slot ID], [Offset in Row] , [Transaction Name] , [Begin Time], [End Time], [Number of Locks] , [Lock Information] , [RowLog Contents 0] , [RowLog Contents 1] , [RowLog Contents 2] , [RowLog Contents 3] , [RowLog Contents 4] , [Log Record], [Log Record Fixed Length] , [Log Record Length] FROM fn_dblog (null,null) WHERE AllocUnitName LIKE '%CreditInfo%' GO
Boom! there is nothing related to CreditInfo object. Didn't I tell you that the log backup cleared the transaction log?
But you can see that data in the data file. Use a simple select.
Ok, this is credit card data and one internet kitten will die for each row you keep in your database. Its vile. So lets get rid of it. After you truncate the table, will you find any information about it in the log file? Yes, you will. You'll see LOP_MODIFY_ROW operation.
TRUNCATE TABLE CreditInfo; SELECT [Previous LSN] , [Current LSN] , [Transaction ID] , [Operation], [CONTEXT], [AllocUnitName] , [Page ID], [Slot ID], [Offset in Row] , [Transaction Name] , [Begin Time], [End Time], [Number of Locks] , [Lock Information] , [RowLog Contents 0] , [RowLog Contents 1] , [RowLog Contents 2] , [RowLog Contents 3] , [RowLog Contents 4] , [Log Record], [Log Record Fixed Length] , [Log Record Length] FROM fn_dblog (null,null) WHERE AllocUnitName LIKE '%CreditInfo%'
The credit card scan utility still sees the data, we just truncated the table and still. Ok, lets do a log backup.
BACKUP LOG storagefun TO DISK = 'D:\SQLData\storagefun_lon1.trn'
Read the log again
SELECT [Previous LSN] , [Current LSN] , [Transaction ID] , [Operation], [CONTEXT], [AllocUnitName] , [Page ID], [Slot ID], [Offset in Row] , [Transaction Name] , [Begin Time], [End Time], [Number of Locks] , [Lock Information] , [RowLog Contents 0] , [RowLog Contents 1] , [RowLog Contents 2] , [RowLog Contents 3] , [RowLog Contents 4] , [Log Record], [Log Record Fixed Length] , [Log Record Length] FROM fn_dblog (null,null) WHERE AllocUnitName LIKE '%CreditInfo%'
Still see the records? How about a checkpoint
CHECKPOINT GO
At this point, if you try to read again, you wont see any records related to CreditInfo and its completely gone. I was able to explain about FULL Recovery mode, nature of log using this example to our devs and I hope you find it useful too.
Wednesday, May 29, 2013
Python Classes and Objects
It took me 4 hours to figure out whats going on with classes and objects in Python and I am not even sure if I understand them completely yet. Yeah, I am dumb. Anyways - I was able to complete this 'Hello World' kind of program for calculating account balance and fees.
__author__ = 'RK Kuppala' class BankAccount: def __init__(self, balance): """Creates an account with the given balance.""" self.balance = balance self.counter = 0 def withdraw(self, amount): """ Withdraws the amount from the account. Each withdrawal resulting in a negative balance also deducts a penalty fee of 5 dollars from the balance. """ if self.balance - amount < 0: self.balance -= amount+5 self.counter += 5 else: self.balance -= amount def deposit(self, amount): """Deposits the amount into the account.""" self.balance += amount def get_balance(self): """Returns the current balance in the account.""" return self.balance def get_fees(self): """Returns the total fees ever deducted from the account.""" return self.counter #lets test if it works my_account = BankAccount(5) my_account.withdraw(15) my_account.deposit(20) my_account.withdraw(60) my_account.deposit(20) my_account.withdraw(60) print my_account.get_balance(), my_account.get_fees()
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:
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.
Subscribe to:
Posts (Atom)