Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Neil Hendren #559

Open
wants to merge 56 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
bd7e146
Add card class without any methods
NeilTheSeal Jan 30, 2024
8032bf6
Add turn class without any methods
NeilTheSeal Jan 30, 2024
6f3093d
Add empty turn_spec file
NeilTheSeal Jan 30, 2024
a0754f8
Finish Turn class specifications
NeilTheSeal Jan 30, 2024
f4fbfb5
Merge pull request #1 from NeilTheSeal/development
NeilTheSeal Jan 30, 2024
8df52cf
Add more properties to attr_reader
NeilTheSeal Jan 30, 2024
c1ec716
Begin spec for Turn
NeilTheSeal Jan 30, 2024
0d40c3a
Add deck class file
NeilTheSeal Jan 30, 2024
514c2bf
Add deck class spec file
NeilTheSeal Jan 30, 2024
d5df39e
Add initial tests in deck spec
NeilTheSeal Jan 30, 2024
5bf5589
Add code for basic deck class
NeilTheSeal Jan 30, 2024
2431f7b
Add count method to Deck class
NeilTheSeal Jan 30, 2024
82dd6ea
Add test for deck.count
NeilTheSeal Jan 30, 2024
2e1f88d
Fix bug in require statement, fix bug in for loop
NeilTheSeal Jan 30, 2024
3c35e23
Add cards_in_category method
NeilTheSeal Jan 30, 2024
3ee2ce5
Fix bug in cards_in_category for loop
NeilTheSeal Jan 30, 2024
c2bc6a0
Add test for cards_in_category
NeilTheSeal Jan 30, 2024
d9096c4
Add class and spec for Round
NeilTheSeal Jan 30, 2024
39f6a0f
Install linting, typechecking, auto-formatting
NeilTheSeal Jan 30, 2024
36d04ce
Corrections by linter
NeilTheSeal Jan 30, 2024
b3ccb5d
Correct formatting using RuboCop
NeilTheSeal Jan 30, 2024
cf06134
Corrections from linter/formatter
NeilTheSeal Jan 30, 2024
486ef3f
Specify test parameters for Round class
NeilTheSeal Jan 30, 2024
b0af1a4
Updated specs to follow convention
NeilTheSeal Jan 30, 2024
05c5985
Adds 'exists' test to Deck spec
NeilTheSeal Jan 30, 2024
20e4adb
Removes unnecessary testing code
NeilTheSeal Jan 30, 2024
555c1f9
Fix typos in Round spec
NeilTheSeal Jan 31, 2024
7207ac8
Complete methods required for iteration 2
NeilTheSeal Jan 31, 2024
6a5a692
Merge pull request #2 from NeilTheSeal/development
NeilTheSeal Jan 31, 2024
37b71b1
Add skeleton for Game class
NeilTheSeal Jan 31, 2024
32c024b
Write game loop and show results
NeilTheSeal Jan 31, 2024
42c3371
Merge pull request #3 from NeilTheSeal/development
NeilTheSeal Jan 31, 2024
f4f3ef2
Remove development Gem specifications
NeilTheSeal Jan 31, 2024
671f35f
Merge pull request #4 from NeilTheSeal/development
NeilTheSeal Jan 31, 2024
70d41ed
Add files for card generation
NeilTheSeal Jan 31, 2024
1de4445
Add CardGenerator spec
NeilTheSeal Jan 31, 2024
b0b3b64
Fill cards.txt with example cards
NeilTheSeal Jan 31, 2024
a661617
Add CardGenerator functionality
NeilTheSeal Jan 31, 2024
a1745b2
Modify flashcard_runner to work with CardGenerator class
NeilTheSeal Jan 31, 2024
a1cd574
Create better cards
NeilTheSeal Jan 31, 2024
feec013
Clarification to question
NeilTheSeal Jan 31, 2024
793c8e0
Make quiz provide correct answer if wrong answer is given
NeilTheSeal Jan 31, 2024
04cd393
Merge pull request #5 from NeilTheSeal/development
NeilTheSeal Jan 31, 2024
a0293bd
Add 'chomp' method to gets input
NeilTheSeal Feb 1, 2024
37d0249
Refactor flashcard_runner
NeilTheSeal Feb 1, 2024
153faaa
Eliminate redundancies in question/answer/category
NeilTheSeal Feb 2, 2024
0d88aab
Add additional tests for Turn spec
NeilTheSeal Feb 6, 2024
c809374
Add last test for Turn spec
NeilTheSeal Feb 6, 2024
bfcfcd3
Add corrections to deck spec
NeilTheSeal Feb 6, 2024
0d1c8d7
Fix bugs in round.rb and round_spec.rb files
NeilTheSeal Feb 6, 2024
ad7996e
Fix bugs in card_spec file
NeilTheSeal Feb 6, 2024
dfed1d1
Remove integer specification; it's unnecessary
NeilTheSeal Feb 6, 2024
2499fc2
Add documentation for each class
NeilTheSeal Feb 6, 2024
76f5da4
Make more edits to documentation
NeilTheSeal Feb 6, 2024
41b8f6e
Move game class into its own file
NeilTheSeal Feb 7, 2024
93bfb50
Refactor classes and tests
NeilTheSeal Feb 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cards.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
What is 10 + 15?,25,math
What is the author of this repository's first name?,Neil,common_knowledge
What is the integral of (x dx) evaluated from 0 to 2?,2,math
Who is the president of the United States as of January 2024?,Joe Biden,common_knowledge
Is pineapple pizza delicious or not (yes or no)?,yes,common_knowledge
Does water have higher density than ethanol?,yes,physics
What is the SI unit for charge?,coulomb,physics
3 changes: 3 additions & 0 deletions flashcard_runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require './lib/game'

Game.new.start
14 changes: 14 additions & 0 deletions lib/card.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# A card containing a question, answer, and cateogory
#
# Syntax:
#
# card = Card.new("question", "answer", :category)
class Card
attr_reader :question, :answer, :category

def initialize(question, answer, category)
@question = question
@answer = answer
@category = category
end
end
33 changes: 33 additions & 0 deletions lib/card_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require './lib/card'

# Generates an array of cards from a .txt file
#
# Syntax:
#
# card_generator = CardGenerator.new(".../file_path.txt")
class CardGenerator
attr_reader :cards, :file_text

def initialize(file_path)
@cards = []
@file_text = ''
@file_path = file_path
end

def parse_file
file = File.open(@file_path)
@file_text += file.read
end

def push_cards
text_array = @file_text.split("\n")
text_array.each do |card_text|
params_array = card_text.split(',')
question = params_array[0]
answer = params_array[1]
category = params_array[2].to_sym
card = Card.new(question, answer, category)
@cards.push(card)
end
end
end
29 changes: 29 additions & 0 deletions lib/deck.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require './lib/card'
require './lib/deck'

# Generates a deck of cards from an array of Card instances. The main
# difference between this class and an array of Cards is the
# .cards_in_category method.
#
# Syntax:
#
# deck = Deck.new([card1, card2, card3...])
class Deck
attr_reader :cards

def initialize(cards)
@cards = cards
end

def count
@cards.length
end

def cards_in_category(category)
num_of_cards = 0
@cards.each do |card|
num_of_cards += 1 if card.category == category
end
num_of_cards
end
end
72 changes: 72 additions & 0 deletions lib/game.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
require './lib/card'
require './lib/deck'
require './lib/round'
require './lib/turn'
require './lib/card_generator'

# This class is the wrapper for the entire flash card CLI.
# It handles the text input and output happening in the terminal.
#
# Syntax:
#
# Game.new.start
#
# Terminal command to start the game:
#
# ruby ...path_to/flashcard_runner.rb
class Game
def initialize
card_generator = CardGenerator.new('cards.txt')
card_generator.parse_file
card_generator.push_cards
@cards = card_generator.cards
@deck = Deck.new(@cards)
@round = Round.new(@deck)
end

def start
puts "\nWelcome! You're playing with #{@deck.count} cards.\n--------------------------------------\n"
quiz_loop
end

def provide_question
puts "This is card number #{@round.turn_number + 1} out of #{@deck.count}"
puts "Question: #{@round.current_card.question}"
end

def provide_feedback(turn)
puts turn.feedback
sleep(1)
puts "--------------------------------------\n"
end

def take_input
provide_question
guess = gets.chomp
turn = @round.take_turn(guess)
provide_feedback(turn)
end

def quiz_loop
take_input while @round.turn_number < @deck.count
show_results
end

def categories_array
list_of_categories = []
@deck.cards.each do |card|
list_of_categories.push(card.category) unless list_of_categories.include?(card.category)
end
list_of_categories
end

def show_results
puts "\n****** Game over! ******\n"
puts "\nYou had #{@round.number_correct} correct guesses out of #{@deck.count} for a total score of #{(100.0 * @round.number_correct / @deck.count).round}%."
list_of_categories = categories_array
list_of_categories.each do |category|
puts "#{category} - #{@round.percent_correct_by_category(category)}% correct"
end
puts ''
end
end
60 changes: 60 additions & 0 deletions lib/round.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require './lib/card'
require './lib/turn'
require './lib/deck'

# A class that provides functionality for the flash cards game.
# It is instantiated from a Deck instance, and has methods to
# compare guesses with answers, count the number of correct answers
# by cateogory, and display the current card.
#
# Syntax:
#
# round = Round.new(deck)
class Round
attr_reader :deck, :turns, :turn_number, :number_correct

def initialize(deck)
@deck = deck
@turns = []
@turn_number = 0
@number_correct = 0
end

def current_card
@deck.cards[@turn_number]
end

def take_turn(guess)
turn = Turn.new(guess, current_card)
turns.push(turn)
@turn_number += 1
@number_correct += 1 if guess == turn.card.answer
turn
end

def correct?
@turns.last.guess == current_card.answer
end

def number_correct_by_category(category)
count_correct = 0
@turns.each do |turn|
count_correct += 1 if turn.card.category == category && turn.guess == turn.card.answer
end
count_correct
end

def total_in_category(category)
count_category = 0
@turns.each do |turn|
count_category += 1 if turn.card.category == category
end
count_category
end

def percent_correct_by_category(category)
number_correct_in_category = number_correct_by_category(category)
number_total_in_category = total_in_category(category)
((number_correct_in_category.to_f / number_total_in_category) * 100).round(1)
end
end
28 changes: 28 additions & 0 deletions lib/turn.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This is a class providing functionality for each individual
# turn in a Round. It has methods to check whether the answer
# for that turn is correct, and provides feedback based on
# whether or not the answer for that turn is correct.
#
# Syntax:
#
# turn = Turn.new("guess", card)
class Turn
attr_reader :card, :guess

def initialize(guess, card)
@guess = guess
@card = card
end

def correct?
@guess == @card.answer
end

def feedback
if @guess.downcase == @card.answer.downcase
'Correct!'
else
"Incorrect. The correct answer is #{@card.answer}"
end
end
end
31 changes: 31 additions & 0 deletions spec/card_generator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# typed: ignore

require './lib/card'
require './lib/turn'
require './lib/deck'
require './lib/round'
require './lib/card_generator'

RSpec.describe CardGenerator do
before(:each) do
@card_generator = CardGenerator.new('cards.txt')
end

it 'exists' do
expect(@card_generator).to be_an_instance_of(CardGenerator)
end

it 'parses text file' do
@card_generator.parse_file
expect(@card_generator.file_text).to(satisfy { |file_text| !file_text.empty? })
end

it 'creates an array of cards of class Card' do
@card_generator.parse_file
@card_generator.push_cards
expect(@card_generator.cards).to(satisfy { |cards| !cards.empty? })
@card_generator.cards.each do |card|
expect(card).to be_an_instance_of(Card)
end
end
end
22 changes: 10 additions & 12 deletions spec/card_spec.rb
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
# typed: ignore

require './lib/card'

RSpec.describe Card do
it 'exists' do
card = Card.new("What is the capital of Alaska?", "Juneau", :Geography)
before(:each) do
@card = Card.new('What is the capital of Alaska?', 'Juneau', :Geography)
end

expect(card).to be_instance_of(Card)
it 'exists' do
expect(@card).to be_instance_of(Card)
end

it 'has a question' do
card = Card.new("What is the capital of Alaska?", "Juneau", :Geography)

expect(card.question).to eq("What is the capital of Alaska?")
expect(@card.question).to eq('What is the capital of Alaska?')
end

it 'has an answer' do
card = Card.new("What is the capital of Alaska?", "Juneau", :Geography)

expect(card.answer).to eq("Juneau")
expect(@card.answer).to eq('Juneau')
end

it 'has a category' do
card = Card.new("What is the capital of Alaska?", "Juneau", :Geography)

expect(card.category).to eq(:Geography)
expect(@card.category).to eq(:Geography)
end
end
36 changes: 36 additions & 0 deletions spec/deck_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# typed: ignore

require './lib/card'
require './lib/turn'
require './lib/deck'

RSpec.describe Deck do
before(:each) do
@cards = [
Card.new('Question 1', 'Answer 1', :category1),
Card.new('Question 2', 'Answer 2', :category1),
Card.new('Question 3', 'Answer 3', :category2)
]
@deck = Deck.new(@cards)
end

it 'exists' do
expect(@deck).to be_an_instance_of(Deck)
end

it 'cards property is an array' do
expect(@deck.cards).to be_an_instance_of(Array)
end

it 'cards array items are correct cards' do
expect(@deck.cards).to eq(@cards)
end

it 'counts number of cards in deck' do
expect(@deck.count).to eq(3)
end

it 'counts number of cards in category' do
expect(@deck.cards_in_category(:category1)).to eq(2)
end
end
Loading