These are code samples from two of my web applications. The first app is StormyKnights, an online chess game. I was a part of a team of four developers that worked on this project. StormyKnights was the capstone app for The Firehose Project, an immersive web development program with a focus on Ruby on Rails. It can be seen live at stormy-knights.herokuapp.com.
The second app is a personal project called My Recipe Box, an app for displaying and sharing recipes. It can be seen at allmyrecipes.herokuapp.com.
This method from the chess game app determines whether the path between a piece and an intended destination is a straight line (either horizontal, vertical, or diagonal). If the path is a straight line, then it checks whether the path is obstructed by another piece. If the path is not a straight line, then it returns an error.
Enter # This method determines whether the path between instance piece and destination is obstructed by another piece. # # * *Args* : # - +destination+ -> array containing x and y coordinates of the piece's intended destination # * *Returns* : # - True if one or more squares between the piece and the destination are occupied # - False otherwise # * *Raises* : # - +RuntimeError+ -> if the path is not a straight line def obstructed?(destination) @game = game # converts the location arrays into easier-to-read x and y terms x1 = self.x_coordinates #assume starting points y1 = self.y_coordinates x2 = destination[0] y2 = destination[1] # Determines whether the line between piece1 and the destination is horizontal or # vertical. If neither, then it calculates the slope of line between piece1 and destination. path = check_path(x1, y1, x2, y2) # path is horizontal and right to left if path == 'horizontal' && x1 < x2 (x1 + 1).upto(x2 - 1) do |x| return true if occupied?(x, y1) end end # path is horizontal and left to right if path == 'horizontal' && x1 > x2 (x1 - 1).downto(x2 + 1) do |x| return true if occupied?(x, y1) end end # path is vertical down if path == 'vertical' && y1 < y2 (y1 + 1).upto(y2 - 1) do |y| return true if occupied?(x1, y) end end # path is vertical up if path == 'vertical' && y1 > y2 (y1 - 1).downto(y2 + 1) do |y| return true if occupied?(x1, y) end end if path == 'horizontal' || path == 'vertical' return false end # path is diagonal and down if @slope.abs == 1.0 && x1 < x2 (x1 + 1).upto(x2 - 1) do |x| delta_y = x - x1 y = y2 > y1 ? y1 + delta_y : y1 - delta_y return true if occupied?(x, y) end end # path is diagonal and up if @slope.abs == 1.0 && x1 > x2 (x1 - 1).downto(x2 + 1) do |x| delta_y = x1 - x y = y2 > y1 ? y1 + delta_y : y1 - delta_y return true if occupied?(x, y) end end # path is not a straight line if @slope.abs != 1.0 fail 'path is not a straight line' else return false end end
These are methods used by obstructed? method shown above.
def occupied?(x, y) game.pieces.where(x_coordinates: x, y_coordinates: y).present? end def check_path(x1, y1, x2, y2) if y1 == y2 return 'horizontal' elsif x1 == x2 return 'vertical' else # move diagonal @slope = (y2 - y1).to_f / (x2 - x1).to_f end end
This method implements a capture if a piece lands on a square occupied by a piece of the opposite color. This is done by setting coordinates of the captured piece to nil and by setting coordinates of the capturing piece to new values.
# This method implements capturing a piece. # # * *Args* : # - +new_x, new_y+ -> x and y coordinates of the piece's intended destination # * *Returns* : # - If intended destination is occupied by piece of the opposite color, # then the occupying piece is removed from the board by setting its coordinates to 'nil' # # * *Raises* : # - +RuntimeError+ -> if intended destination is occupied by piece of same color def move_to!(new_x, new_y) @game = game if occupied?(new_x, new_y) @piece_at_destination = @game.pieces.find_by(x_coordinates: new_x, y_coordinates: new_y) if color == @piece_at_destination.color fail 'destination occupied by piece of same color' else @piece_at_destination.update_attributes(x_coordinates: nil, y_coordinates: nil, status: 'captured') @status = @piece_at_destination.status @captured = true end else @captured = false end end
This method implements a move. It checks whether the intended move is valid by executing the valid_move? method belonging to the piece's subclass. If the move is a castling, then it calls the castling_to? method. It calls the move_to! method to check whether the destination is occupied and to perform a capture if appropriate.
# This method implements a move. It checks whether the intended move is valid # by executing the valid_move? method belonging to the piece's subclass. # If the move is a castling, then it calls the castling_to? method. # It calls the move_to! method to check whether the destination is occupied and to # perform a capture if appropriate. # Assigns values to instance variables @castle (true if the move is a castling, # @valid (true if the move does not violate the rules of chess, # and @not_color (assigned to the color belonging to player with the next move) # # * *Args* : # - +new_x, new_y+ -> x and y coordinates of the piece's intended destination # * *Returns* : # - Assigns values to instance variables @castle, @valid, and @not_color # def perform_move!(x_coordinates, y_coordinates) valid_move_result = self.valid_move?(x_coordinates, y_coordinates) if self.castling_to?(x_coordinates, y_coordinates) @castle = true castling(x_coordinates) elsif valid_move_result self.move_to!(x_coordinates, y_coordinates) if update_attributes(x_coordinates: x_coordinates, y_coordinates: y_coordinates) @valid = true end else @valid = false end if color == 'white' @not_color = 'black' else @not_color = 'white' end end
This is the model file for Recipe class in My Recipe Box app. It contains the search method that implements a search from the input box on the title page.
class Recipe < ActiveRecord::Base belongs_to :user has_many :comments validates :name, :presence => true, length: { minimum: 3 } validates :ingredients, :presence => true validates :instructions, :presence => true # Implements search for recipes. # * *Args* : # - search query in string format # * *Returns* : # - returns the recipes with names that contain one or more words from the query def self.search(query) #where(:title, query) -> This would return an exact match of the query where("LOWER(name) like ?", "%#{query}%") end # Calculates the average rating of recipe # * *Args* : # None # * *Returns* : # - average rating of recipe def avg_rating rating_vals = self.comments.map do |c| c.rating[0].to_i end rating_vals.sum.to_f / rating_vals.length end end