From 2755254e7e0c7e84054fd9224dd34e381912129a Mon Sep 17 00:00:00 2001 From: Juliet Eyraud Date: Tue, 14 May 2024 17:54:11 -0500 Subject: [PATCH 1/4] add war or peace as alternative first solo project --- module1/projects/war_or_peace/index.md | 25 ++ module1/projects/war_or_peace/iteration1.md | 128 ++++++++ module1/projects/war_or_peace/iteration2.md | 284 ++++++++++++++++++ module1/projects/war_or_peace/iteration3.md | 72 +++++ module1/projects/war_or_peace/iteration4.md | 49 +++ module1/projects/war_or_peace/requirements.md | 23 ++ module1/projects/war_or_peace/rubric.md | 38 +++ module1/projects/war_or_peace/setup.md | 20 ++ module1/projects/war_or_peace/submission.md | 17 ++ 9 files changed, 656 insertions(+) create mode 100644 module1/projects/war_or_peace/index.md create mode 100644 module1/projects/war_or_peace/iteration1.md create mode 100644 module1/projects/war_or_peace/iteration2.md create mode 100644 module1/projects/war_or_peace/iteration3.md create mode 100644 module1/projects/war_or_peace/iteration4.md create mode 100644 module1/projects/war_or_peace/requirements.md create mode 100644 module1/projects/war_or_peace/rubric.md create mode 100644 module1/projects/war_or_peace/setup.md create mode 100644 module1/projects/war_or_peace/submission.md diff --git a/module1/projects/war_or_peace/index.md b/module1/projects/war_or_peace/index.md new file mode 100644 index 00000000..9337decf --- /dev/null +++ b/module1/projects/war_or_peace/index.md @@ -0,0 +1,25 @@ +--- +layout: page +title: War or Peace +--- + +## Learning Goals + +* Follow an interaction pattern +* Write readable code that adheres to Ruby convention +* Write tests +* Create an Object Oriented Solution to a problem (objects should interact to achieve the stated goal) +* Host code on Github and submit a Pull Request + +## Overview + +In this project, you will write a program to simulate a game of [war](https://en.wikipedia.org/wiki/War_(card_game)). A user will be able to create two players, and watch them 'play' the game. + +In order to build good habits, we've broken the project into small classes to demonstrate objects that have a single responsibility. + +Additional detail is included in the pages below. + +* [Setup](./setup) +* [Project Requirements](./requirements) +* [Submission](./submission) +* [Evaluation Rubric & Presentation Guidelines](./rubric) \ No newline at end of file diff --git a/module1/projects/war_or_peace/iteration1.md b/module1/projects/war_or_peace/iteration1.md new file mode 100644 index 00000000..e4e46afb --- /dev/null +++ b/module1/projects/war_or_peace/iteration1.md @@ -0,0 +1,128 @@ +--- +layout: page +title: War or Peace - Iteration 1 +--- + +_[Back to Project Home](./index)_ +_[Back to Requirements](./requirements)_ + +## Iteration 1 + +### Cards + +A `Card` represents a single card that would be in a traditional deck of 52 cards. + +Use the tests provided to drive the development of your `Card` class. **From the root directory of your project, run the test like this**: + +``` +rspec spec/card_spec.rb +``` + +If you haven't already, you will need to install rspec: + +``` +gem install rspec +``` + +If your `Card` class is written properly and is located at `./lib/card.rb`, you should be able to open a pry session from your `war_or_peace` directory and interact with it like so: + +```ruby +# double check that you are in your war_or_peace project directory! +pry(main)> require './lib/card' +#=> true + +pry(main)> card = Card.new(:heart, 'Jack', 11) +#=> # + +pry(main)> card.suit +#=> :heart + +pry(main)> card.value +#=> "Jack" + +pry(main)> card.rank +#=> 11 +``` + + +### Deck + +Create a `Deck` class and an accompanying test file with the following instance methods: + +* `initialize`: this method will take one argument - an array of cards. +* `cards`: an attr_reader to read the `@cards` attribute +* `rank_of_card_at`: this method will take one argument that represents the index location of a card to be used (typically `0` or `2` *more on this later 😉* ) and will return the rank of that card. +* `high_ranking_cards`: this method will return an array of cards in the deck that have a rank of 11 or above (face cards and aces) +* `percent_high_ranking`: this method will return the percentage of cards that are high ranking +* `remove_card`: this method will remove the top card from the deck +* `add_card`: this method will add one card to the bottom (end) of the deck + +Use the interaction pattern below to help you build your Deck test and `Deck` class. + +Remember, `#` means "A Card Object" or "An Instance of the Card Class". If you need to verify _which_ card object it is, you can refer to the last few digits of the 'random' letters and numbers and match those to a card that is created near the top of the interaction pattern. + +```ruby +pry(main)> require './lib/card' +#=> true + +pry(main)> require './lib/deck' +#=> true + +pry(main)> card1 = Card.new(:diamond, 'Queen', 12) +#=> # + +pry(main)> card2 = Card.new(:spade, '3', 3) +#=> # + +pry(main)> card3 = Card.new(:heart, 'Ace', 14) +#=> # + +pry(main)> cards = [card1, card2, card3] + +pry(main)> deck = Deck.new(cards) +#=> #, #, #]> + +pry(main)> deck.cards +#=> [#, #, #] + +pry(main)> deck.rank_of_card_at(0) +#=> 12 + +pry(main)> deck.rank_of_card_at(2) +#=> 14 + +pry(main)> deck.cards +#=> [#, #, #] + +pry(main)> deck.high_ranking_cards +#=> [#, #] + +pry(main)> deck.percent_high_ranking +#=> 66.67 + +pry(main)> deck.remove_card +#=> # + +pry(main)> deck.cards +#=> [#, #] + +pry(main)> deck.high_ranking_cards +#=> [#] + +pry(main)> deck.percent_high_ranking +#=> 50.0 + +pry(main)> card4 = Card.new(:club, '5', 5) +#=> # + +pry(main)> deck.add_card(card4) + +pry(main)> deck.cards +#=> [#, #, #] + +pry(main)> deck.high_ranking_cards +#=> [#] + +pry(main)> deck.percent_high_ranking +#=> 33.33 +``` \ No newline at end of file diff --git a/module1/projects/war_or_peace/iteration2.md b/module1/projects/war_or_peace/iteration2.md new file mode 100644 index 00000000..58607e5f --- /dev/null +++ b/module1/projects/war_or_peace/iteration2.md @@ -0,0 +1,284 @@ +--- +layout: page +title: War or Peace - Iteration 2 +--- + +_[Back to Project Home](./index)_ +_[Back to Requirements](./requirements)_ + +## Iteration 2 + +### Player + +Create a `Player` class with accompanying tests. A `Player` is initialized with a deck, and can determine if they have lost the game. + +```ruby +pry(main)> require './lib/card' +#=> true + +pry(main)> require './lib/deck' +#=> true + +pry(main)> require './lib/player' +#=> true + +pry(main)> card1 = Card.new(:diamond, 'Queen', 12) +#=> # + +pry(main)> card2 = Card.new(:spade, '3', 3) +#=> # + +pry(main)> card3 = Card.new(:heart, 'Ace', 14) +#=> # + +pry(main)> deck = Deck.new([card1, card2, card3]) +#=> #, #, #]> + +pry(main)> player = Player.new('Clarisa', deck) +#=> #, #, #]>, @name="Clarisa"> + +pry(main)> player.name +#=> "Clarisa" + +pry(main)> player.deck +#=> #, #, #]> + +pry(main)> player.has_lost? +#=> false + +pry(main)> player.deck.remove_card +#=> # + +pry(main)> player.has_lost? +#=> false + +pry(main)> player.deck.remove_card +#=> # + +pry(main)> player.has_lost? +#=> false + +pry(main)> player.deck.remove_card +#=> # + +pry(main)> player.has_lost? +#=> true + +pry(main)> player.deck +#=> # +``` + +### Turn + +The `Turn` is responsible for much of the logic of the game and will respond to the following methods: + +* `initialize`: A Turn is created with two players - player1 and player2 +* readable attributes for `player1`, `player2`, and `spoils_of_war` +* `type`: a turn is `:basic`, `:war`, or `:mutually_assured_destruction`. + * A `:basic` turn is one in which the `rank_of_card_at(0)` from the players' decks are **not** the same rank. + * A `:war` turn occurs when both players' `rank_of_card_at(0)` are the **same**. + * `:mutually_assured_destruction` occurs when both players' `rank_of_card_at(0)` AND `rank_of_card_at(2)` are the **same**. +* `winner`: this method will determine the winner of the turn. + * if the turn has a type of `:basic`, it will return whichever `player` has a higher `rank_of_card_at(0)` + * if the turn has a type of `:war` the winner will be whichever player has a higher `rank_of_card_at(2)` + * if the turn has a type of `:mutually_assured_destruction` the method will return `No Winner`. +* `pile_cards`: when this method is called, cards will be sent from the players' decks into the `@spoils_of_war` based on these rules + * for a `:basic` turn, each player will send one card (the top card) to the `spoils` pile + * for a `:war` turn, each player will send three cards (the top three cards) to the `spoils` pile + * for a `:mutually_assured_destruction` turn, each player will remove three cards from play (the top three cards in their deck). These cards are **not** sent to the `spoils` pile, they are simply removed from each players' deck. +* `award_spoils`: this method will add each of the cards in the `@spoils_of_war` array to the `winner` of the turn. + +The three interaction patterns below highlight the behavior of each type of turn. + +```ruby +#turn type :basic +pry(main)> require './lib/card' +#=> true +pry(main)> require './lib/deck' +#=> true +pry(main)> require './lib/player' +#=> true +pry(main)> require './lib/turn' +#=> true + +pry(main)> card1 = Card.new(:heart, 'Jack', 11) +#=> # +pry(main)> card2 = Card.new(:heart, '10', 10) +#=> # +pry(main)> card3 = Card.new(:heart, '9', 9) +#=> # +pry(main)> card4 = Card.new(:diamond, 'Jack', 11) +#=> # +pry(main)> card5 = Card.new(:heart, '8', 8) +#=> # +pry(main)> card6 = Card.new(:diamond, 'Queen', 12) +#=> # +pry(main)> card7 = Card.new(:heart, '3', 3) +#=> # +pry(main)> card8 = Card.new(:diamond, '2', 2) +#=> # + +pry(main)> deck1 = Deck.new([card1, card2, card5, card8]) +#=> #, #, #, #]> + +pry(main)> deck2 = Deck.new([card3, card4, card6, card7]) +#=> #, #, #, #]> + +pry(main)> player1 = Player.new("Megan", deck1) +#=> #, @name="Megan"> + +pry(main)> player2 = Player.new("Aurora", deck2) +#=> #, @name="Aurora"> + +pry(main)> turn = Turn.new(player1, player2) +#=> #, @player2=#, @spoils_of_war=[]> + +pry(main)> turn.player1 +#=> #, @name="Megan"> + +pry(main)> turn.player2 +#=> #, @name="Aurora"> + +pry(main)> turn.spoils_of_war +#=> [] + +pry(main)> turn.type +#=> :basic + +pry(main)> winner = turn.winner +#=> #, @name="Megan"> + +pry(main)> turn.pile_cards + +pry(main)> turn.spoils_of_war +#=> [#, #] + +pry(main)> turn.award_spoils(winner) + +pry(main)> player1.deck +#=> #, #, #, #, #]> +pry(main)> player2.deck +#=> #, #, #]> +``` + +```ruby +# turn type :war +pry(main)> require './lib/card' +#=> true +pry(main)> require './lib/deck' +#=> true +pry(main)> require './lib/player' +#=> true +pry(main)> require './lib/turn' +#=> true + +pry(main)> card1 = Card.new(:heart, 'Jack', 11) +#=> # +pry(main)> card2 = Card.new(:heart, '10', 10) +#=> # +pry(main)> card3 = Card.new(:heart, '9', 9) +#=> # +pry(main)> card4 = Card.new(:diamond, 'Jack', 11) +#=> # +pry(main)> card5 = Card.new(:heart, '8', 8) +#=> # +pry(main)> card6 = Card.new(:diamond, 'Queen', 12) +#=> # +pry(main)> card7 = Card.new(:heart, '3', 3) +#=> # +pry(main)> card8 = Card.new(:diamond, '2', 2) +#=> # + +pry(main)> deck1 = Deck.new([card1, card2, card5, card8]) +#=> #, #, #, #]> + +pry(main)> deck2 = Deck.new([card4, card3, card6, card7]) +#=> #, #, #, #]> + +pry(main)> player1 = Player.new("Megan", deck1) +#=> #, @name="Megan"> + +pry(main)> player2 = Player.new("Aurora", deck2) +#=> #, @name="Aurora"> + +pry(main)> turn = Turn.new(player1, player2) +#=> #, @name="Megan">, @player2=#, @name="Aurora">, @spoils_of_war=[]> + +pry(main)> turn.type +#=> :war + +pry(main)> winner = turn.winner +#=> #, @name="Aurora"> + +pry(main)> turn.pile_cards + +pry(main)> turn.spoils_of_war +#=> [#, #, #, #, #, #] + +pry(main)> turn.award_spoils(winner) + +pry(main)> player1.deck +#=> #]> + +pry(main)> player2.deck +#=> #, #, #, #, #, #, #]> +``` + +```ruby +# turn type :mutually_assured_destruction +pry(main)> require './lib/card' +#=> true +pry(main)> require './lib/deck' +#=> true +pry(main)> require './lib/player' +#=> true +pry(main)> require './lib/turn' +#=> true + +pry(main)> card1 = Card.new(:heart, 'Jack', 11) +#=> # +pry(main)> card2 = Card.new(:heart, '10', 10) +#=> # +pry(main)> card3 = Card.new(:heart, '9', 9) +#=> # +pry(main)> card4 = Card.new(:diamond, 'Jack', 11) +#=> # +pry(main)> card5 = Card.new(:heart, '8', 8) +#=> # +pry(main)> card6 = Card.new(:diamond, '8', 8) +#=> # +pry(main)> card7 = Card.new(:heart, '3', 3) +#=> # +pry(main)> card8 = Card.new(:diamond, '2', 2) +#=> # + +pry(main)> deck1 = Deck.new([card1, card2, card5, card8]) +#=> #, #, #, #]> + +pry(main)> deck2 = Deck.new([card4, card3, card6, card7]) +#=> #, #, #, #]> + +pry(main)> player1 = Player.new("Megan", deck1) +#=> #, @name="Megan"> + +pry(main)> player2 = Player.new("Aurora", deck2) +#=> #, @name="Aurora"> + +pry(main)> turn = Turn.new(player1, player2) +#=> #, @name="Megan">, @player2= #, @name="Aurora">, @spoils_of_war=[]> + +pry(main)> turn.type +#=> :mutually_assured_destruction + +pry(main)> winner = turn.winner +#=> "No Winner" + +pry(main)> turn.pile_cards + +pry(main)> turn.spoils_of_war +#=> [] +pry(main)> player1.deck +#=> #]> +pry(main)> player2.deck +#=> #]> +``` \ No newline at end of file diff --git a/module1/projects/war_or_peace/iteration3.md b/module1/projects/war_or_peace/iteration3.md new file mode 100644 index 00000000..986e7ec3 --- /dev/null +++ b/module1/projects/war_or_peace/iteration3.md @@ -0,0 +1,72 @@ +--- +layout: page +title: War or Peace - Iteration 3 +--- + +_[Back to Project Home](./index)_ +_[Back to Requirements](./requirements)_ + +## Iteration 3 + +### Play the Game! + +So far we've focused on modeling the data, classes, and methods that make up our game. However we haven't done much in the way of setting up the game to be played. Now, we will tackle that problem. + +A few key points to keep in mind as you work on this iteration: + +* Use `p` to display a line of text output to the user +* In this iteration we'll introduce a new file called a "runner" -- its job is to serve as the main entry point to our program by starting up a new game + +**First**, create your runner file: + +``` +touch war_or_peace_runner.rb +``` + +Inside of this file, write the code to do the following: + +* Create 52 Cards (A standard deck) +* Put those card into two Decks (some randomness would be nice here!) +* Create two players with the Decks you created +* **Start** the game using a new method called `start` + * This method will need to be included in a class - it is up to you which class to include it in - either existing or ✨new ✨ + +**Keep in mind** that your existing objects should still pass all existing tests - nothing that you add in this iteration should break anything that functioned in iterations 1 or 2! + +When we start the game by running `ruby war_or_peace_runner.rb`, it should produce the following interaction from the command line: + + +``` +Welcome to War! (or Peace) This game will be played with 52 cards. +The players today are Megan and Aurora. +Type 'GO' to start the game! +------------------------------------------------------------------ +``` + +Then a user will be able to type `GO`, and a game will start. The user will then see each turn being played, like this: + +``` +Turn 1: Megan won 2 cards +Turn 2: WAR - Aurora won 6 cards +Turn 3: *mutually assured destruction* 6 cards removed from play +... +... +... +Turn 9324: Aurora won 2 cards +*~*~*~* Aurora has won the game! *~*~*~* +``` + +The game continues until one player has all cards in play, at which point, that player is declared the winner of the game! *Hint: take a look at the classes that you have built already, is there a method that will help you determine when the game has been won? or lost?* + +In this game, there is the possibility of no winner. In order to cut down the amount of time it takes to play each game, and ensure that the game eventually does end, only 1,000,000 turns will be allowed. If no player has all cards after 1,000,000 turns, the result of the game is a draw. + +``` +Turn 1: Megan won 2 cards +Turn 2: WAR - Aurora won 6 cards +Turn 3: *mutually assured destruction* 6 cards removed from play +... +... +... +Turn 1000000: Aurora won 2 cards +---- DRAW ---- +``` \ No newline at end of file diff --git a/module1/projects/war_or_peace/iteration4.md b/module1/projects/war_or_peace/iteration4.md new file mode 100644 index 00000000..8671a273 --- /dev/null +++ b/module1/projects/war_or_peace/iteration4.md @@ -0,0 +1,49 @@ +--- +layout: page +title: War or Peace - Iteration 4 +--- + +_[Back to Project Home](./index)_ +_[Back to Requirements](./requirements)_ + +## Iteration 4 + +### Loading Text Files + +Right now, we're hardcoding the cards into our runner. Wouldn't it be nice to have file of card information to use? + +Let's build an object that will read in a text file and generate cards. Remember to using TDD for this iteration! + +Assuming we have a text file `cards.txt` that looks like this (but with all 52 cards): + +``` +2, Heart, 2 +3, Heart, 3 +4, Heart, 4 +5, Heart, 5 +6, Heart, 6 +7, Heart, 7 +8, Heart, 8 +9, Heart, 9 +10, Heart, 10 +Jack, Heart, 11 +Queen, Heart, 12 +King, Heart, 13 +Ace, Heart, 14 +... +``` + +Then we should be able to do this: + +```ruby +pry(main)> require './lib/card_generator' +#=> true + +pry(main)> filename = "cards.txt" +#=> "cards.txt" + +pry(main)> cards = CardGenerator.new(filename).cards +#=> [#, ... #] +``` + +Modify your program so that when you run `ruby war_or_peace_runner.rb`, it uses cards from `cards.txt` instead of hardcoded cards. \ No newline at end of file diff --git a/module1/projects/war_or_peace/requirements.md b/module1/projects/war_or_peace/requirements.md new file mode 100644 index 00000000..a2e0851b --- /dev/null +++ b/module1/projects/war_or_peace/requirements.md @@ -0,0 +1,23 @@ +--- +layout: page +title: War or Peace - Requirements +--- + +_[Back to Project Home](./index)_ + + +In order to help you to organize your project, we have broken the requirements into four separate iterations. It is expected that you will complete iterations 1-3, while 4 includes extensions that represent opportunities to further explore. + +* [Iteration 1](./iteration1) +* [Iteration 2](./iteration2) +* [Iteration 3](./iteration3) +* [Iteration 4](./iteration4) + +In addition to the functionality outlined in these iterations, we will expect you to do the following: + +* write tests for each class +* write readable code +* make frequent commits +* use pull requests + +For more detailed information about what we expect, please review the [rubric](./rubric) before starting this project! \ No newline at end of file diff --git a/module1/projects/war_or_peace/rubric.md b/module1/projects/war_or_peace/rubric.md new file mode 100644 index 00000000..a8b12f6f --- /dev/null +++ b/module1/projects/war_or_peace/rubric.md @@ -0,0 +1,38 @@ +--- +layout: page +title: War or Peace - Rubric +--- + +_[Back to Project Home](./index)_ + + +## Learning Goals + +* Follow an interaction pattern +* Write readable code that adheres to Ruby convention +* Write tests +* Create an Object Oriented Solution to a problem (objects should interact to achieve the stated goal) +* Host code on Github + +
+ +### Presentation Guidelines + +Each student will have a live evaluation with an instructor, and should come prepared to do the following: +* Demonstrate how the game works by running it in the terminal (note: if you don't complete Iteration 3, you can skip this demo) +* Run your tests and identify one test case you're proud of, and one test case you'd like feedback on +* At a high level (i.e. *don't* just read your code line by line) discuss your strategy for implementing one of the more complex methods, such as determining the winner of a Turn, awarding the spoils of war, etc. +* Give a brief overview of how you used your runner.rb file to set up the game play +* Identify an area you would refactor if you had more time +* Ask any remaining questions about the project or their solution +
+ +
| **Exceptional** | **Meets Expectations** | **Below Expectations** | **Well Below Expectations** +-- | --- | --- | --- | --- +**Functionality** | Application is robust and can handle a variety of inputs including invalid inputs and completes iteration 4 | Application adheres to the flow outlined in the specification and can handle a variety of valid inputs (not just what is outlined in spec). Iteration 3 is complete. | Only up to Iteration 2 is complete or the application does not follow the flow outlined in the specification. | Iteration 2 is not complete. | +**Ruby Mechanics** | Project includes appropriate uses of hashes and enumerables not covered in class | Appropriately uses Ruby's built in datatypes and methods, flow control, and enumerables. | Does not appropriately use one or two of the following: Ruby's built in datatypes and methods, flow control, and enumerables | Does not appropriately use Ruby's built in datatypes and methods, flow control, and enumerables, or does not build classes | +**Ruby Conventions** | Classes, methods, and variables are well named so that they clearly communicate their purpose. Code is all properly indented and syntax is consistent. | Code is mostly properly indented, spaced, and lines are not excessively long. Class, method, variable, and file names follow convention | Code demonstrates some proper indenting and spacing. Class, method, variable, and file names inconsistently follow convention | Code is not properly indented and spaced and lines are excessively long. Class, method, variable, and file names do not follow convention | +**Testing** | All methods that do not require command line input/output are accurately tested. Best use assertions are made. | Each class has its own test file. Every method listed on the specification is tested. Most tests are written to accurately verify expected behavior. | Tests are written for most methods listed on the specification, but the tests may be in an incorrect location or the tests may not accurately verify the expected behavior | Fewer than 7 tests written (in addition to the card tests provided) | + +## Version Control +Code is required to be hosted on a GitHub repository, and will have at least 20 commits and one pull request. \ No newline at end of file diff --git a/module1/projects/war_or_peace/setup.md b/module1/projects/war_or_peace/setup.md new file mode 100644 index 00000000..9baa34b0 --- /dev/null +++ b/module1/projects/war_or_peace/setup.md @@ -0,0 +1,20 @@ +--- +layout: page +title: War or Peace - Setup +--- + +_[Back to Project Home](./index)_ + + +* Fork [this repository](https://github.com/turingschool-examples/war_or_peace) +* Clone YOUR fork to your computer +* Make sure you don't clone the turingschool-examples repository + * You can confirm that you have cloned the correct repository by running `git remote -v`. You should see something like this: + + ``` + origin git@github.com:/war_or_peace.git (fetch) + origin git@github.com:/war_or_peace.git (push) + ``` + +* Complete the iterations included in the project requirements +* Remember to commit frequently! \ No newline at end of file diff --git a/module1/projects/war_or_peace/submission.md b/module1/projects/war_or_peace/submission.md new file mode 100644 index 00000000..478a9cd0 --- /dev/null +++ b/module1/projects/war_or_peace/submission.md @@ -0,0 +1,17 @@ +--- +layout: page +title: War or Peace - Submission +--- + +_[Back to War or Peace Home](./index)_ + +To submit your project, fill out the form in the Project Due calendar event and make a Pull Request(PR) from YOUR repository back to Turing's starter repository. + +To make your PR, make sure your code is pushed up to your repository on Github. All the code for your submission should be on the master branch. Then, follow these steps to submit a Pull Request to the turingschool-examples repository: + +1. Go to your projects Github page +1. Click the "Pull Requests" tab ![Imgur](https://i.imgur.com/cQrcknU.png) +1. From the Pull Requests page, click the "New pull request" button ![Imgur](https://i.imgur.com/RgrzM5t.png) +1. Make sure the PR is from your master to the turingschool-examples master ![Imgur](https://i.imgur.com/ieLgjQv.png) +1. Put your name as the title of the PR ![Imgur](https://i.imgur.com/bQlPmj8.png) +1. Click "Create pull request" \ No newline at end of file From 156a357631112e22581ae73b8186772ecd49661c Mon Sep 17 00:00:00 2001 From: Juliet Eyraud Date: Tue, 14 May 2024 17:58:47 -0500 Subject: [PATCH 2/4] update futbol version and add connect four as alternate pair project --- module1/projects/connect_four/c4.jpg | Bin 0 -> 61537 bytes module1/projects/connect_four/evaluation.md | 39 ++++++++ module1/projects/connect_four/index.md | 29 ++++++ module1/projects/connect_four/iteration_1.md | 39 ++++++++ module1/projects/connect_four/iteration_2.md | 33 +++++++ module1/projects/connect_four/iteration_3.md | 77 +++++++++++++++ module1/projects/connect_four/iteration_4.md | 41 ++++++++ module1/projects/connect_four/overview.md | 73 ++++++++++++++ .../projects/connect_four/peer_code_share.md | 23 +++++ module1/projects/connect_four/requirements.md | 20 ++++ module1/projects/connect_four/rubric.md | 19 ++++ module1/projects/connect_four/setup.md | 23 +++++ module1/projects/futbol/evaluation.md | 39 -------- module1/projects/futbol/index.md | 58 ----------- module1/projects/futbol/iterations/file_io.md | 50 ---------- module1/projects/futbol/rubric.md | 23 ----- module1/projects/futbol_pd/evaluation.md | 34 +++++++ module1/projects/futbol_pd/index.md | 62 ++++++++++++ .../iterations/command_line.md | 0 .../futbol_pd/iterations/file_io_stats.md | 93 ++++++++++++++++++ .../iterations/game_statistics.md | 0 .../futbol_pd/iterations/group_norms.md | 48 +++++++++ .../iterations/league_statistics.md | 0 .../iterations/reorganization.md | 0 .../projects/futbol_pd/iterations/retro.md | 33 +++++++ .../iterations/season_statistics.md | 0 .../iterations/statistics.md | 6 +- .../iterations/team_statistics.md | 8 +- .../iterations/website.md | 0 .../{futbol => futbol_pd}/kick_off/index.md | 0 module1/projects/futbol_pd/rubric.md | 23 +++++ 31 files changed, 717 insertions(+), 176 deletions(-) create mode 100644 module1/projects/connect_four/c4.jpg create mode 100644 module1/projects/connect_four/evaluation.md create mode 100644 module1/projects/connect_four/index.md create mode 100644 module1/projects/connect_four/iteration_1.md create mode 100644 module1/projects/connect_four/iteration_2.md create mode 100644 module1/projects/connect_four/iteration_3.md create mode 100644 module1/projects/connect_four/iteration_4.md create mode 100644 module1/projects/connect_four/overview.md create mode 100644 module1/projects/connect_four/peer_code_share.md create mode 100644 module1/projects/connect_four/requirements.md create mode 100644 module1/projects/connect_four/rubric.md create mode 100644 module1/projects/connect_four/setup.md delete mode 100644 module1/projects/futbol/evaluation.md delete mode 100644 module1/projects/futbol/index.md delete mode 100644 module1/projects/futbol/iterations/file_io.md delete mode 100644 module1/projects/futbol/rubric.md create mode 100644 module1/projects/futbol_pd/evaluation.md create mode 100644 module1/projects/futbol_pd/index.md rename module1/projects/{futbol => futbol_pd}/iterations/command_line.md (100%) create mode 100644 module1/projects/futbol_pd/iterations/file_io_stats.md rename module1/projects/{futbol => futbol_pd}/iterations/game_statistics.md (100%) create mode 100644 module1/projects/futbol_pd/iterations/group_norms.md rename module1/projects/{futbol => futbol_pd}/iterations/league_statistics.md (100%) rename module1/projects/{futbol => futbol_pd}/iterations/reorganization.md (100%) create mode 100644 module1/projects/futbol_pd/iterations/retro.md rename module1/projects/{futbol => futbol_pd}/iterations/season_statistics.md (100%) rename module1/projects/{futbol => futbol_pd}/iterations/statistics.md (94%) rename module1/projects/{futbol => futbol_pd}/iterations/team_statistics.md (77%) rename module1/projects/{futbol => futbol_pd}/iterations/website.md (100%) rename module1/projects/{futbol => futbol_pd}/kick_off/index.md (100%) create mode 100644 module1/projects/futbol_pd/rubric.md diff --git a/module1/projects/connect_four/c4.jpg b/module1/projects/connect_four/c4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d05cc6216a1f558152163df0859101e961f3f7b3 GIT binary patch literal 61537 zcmbTdWmH>T)CL%=X^RziXbTi8R$Nn{K!M^~v@P!L5}X!yil(>|+zG`C6e#W%+!Hid z7~b!jHM7?InwgW8`{$msv!C2^_IdVm_I;RpSOdIJlv9ucU|;|M7>^&o!y-TifP;mN zjg5u#c)`KJc>=_H3VdvYxVX>ohzN;^i3o{^NXTg^NJy#4h=?d(QBu>Ldf0ES0D zaWMX;0sha1fr*9v=;hOA&v73+G`s*{VqjrmKKlO%;IX&=<9z@&5f1SyUa2P}>R*Ac zok`yXCFDM3l&h@ry--jq{5439*zq@T)V)>vus@@XK* zzPXG)CuibcXGZ=9?SGK{zXKNh{|njw1?>OEwE)1w!gzdmSVRC2;Fdj-_2wUjEOwZN zLO&bXbSxI8a|S@4%~_5WgSD`a@)veq8mStly8M%9H4IrmY;bDIZ$&m|g@k>!Ky^7e zVMbEtNq&I3oOd55fSHt7>}pR@vgL75Y9v6B6`qFq*qb#k>KC565^DU@qpe8c|14rY z-et4KWff*3tOQ_23XihA;|uowg_9Q)aw2v0XfIOV%A7O$a)biIDxXpK&j{E5ctZ+E z))@b9=>K|`7f2kfF=4rq@|*Qn{1XMN1BDjrzW+M%t+Qpw>3bxN(yg0h($Ld z0WmOl;ZapZ1Vhv+@r8n)&Vo>=yXIH(A`-gg&G!tFrVoI(UFdxRbWsP^hGnEXC$Pt& zM>_m-L-q&CJgX$n`TT(qwi`G42Y@1ij!?0Bazkgjp3XokRj}71(VUY`{?#ViS(_!w z$Fx*}WAgXc>1^x%gS<0gX91)8WFv^nJtX$d+nYud)em17r+Kpe+cIf(=)I5v%8C7G zw$G&YFiLIa&e4i+$TGTzk>mkjhgs}^z916VT-Qo17OTp0soC}qkMz46nybnWsZbF*FwW& z(>poHez8Np97prUWO0M@OwV?LZ6Z-EDaTi%>rBSRX5`W(kui6#!Jzo{bAtg#yV~@Q z&w#CD&#%9`%4VA&#BZYybHp>?E9B3Z2U2r%&c?~YJwdmx>*2_^x;iAwu#860VL~?h zfIg0H1OoG!){|&c5vtFF;*XGex5W1@6=+J~KcT6q_#aNuF%Q!5wy_56UVep;y)u!_Myz#M!M+y06hAnWo z-_SvQKfpNWo^5vF61H32gBZ|ij&gX>SQYMJar<}2VRFn_9bcxeRkl75_4VttnQ{gB zUqj|RlJ4}U_lMc2?l>7Eo>akt7Di>}?J$iT@+|L`%;m7O6>u=J9X`csIj=NFQbc8J!BweH6>`k%u{Uf_K3?wpU32pE>r}B7r4;9&+azI# zFy?NHq|z~}+ZQ+Y#imJ`v=to)cXX>1>hhV%^!I!gF7|_Gkl+~CuN}cR z(OfPyq@Y=Bekv4FZ;<=|;QJZTNB^d^u{D*D!7K9U6~>2DAKjm|N^$9ry91CmLx9tD zz$1fWwQD2$+xEq`SlL?iu=&c!Rg#$3g4nr4x$gQ&oCShAwBk;}a!uI*{jo`)uV06k zDcVI3k0drEV>qrqhfVc|tJjbbhjGq$av>~c`<-0K7d5@0kmZ`#3*KCV^o8fclj^r0 zU7)_Y`&tix(7OKcm99c0y3m$+@B#42AVwtLfcJ2&C(B2ZWPth*Q73~`+}j~}hii2h zMc4M7FkaLYGC)>?WE@yHiMeBRULW+M@h`;v!RRXDk>C_dn~NdUV@gXOI#U#eR54;7 zx8Fc%GM8%2w{`^wONPAz5nDNz4uUPAe{9q`TI#QVQs`gB*oV3dBZ)6wx&8D>#-(4n6GU*FM}5noU&zIK zPmw75{>I1ehf7R-PUpJ}uc!ffaPlh25s^MlGaoUY;%C>b9jYZzdYPzW^c~nAJ5hP# z$N850T)C^Ary_90y!#w0;lM~XE~K54zQNoX6mchk&11w=do6n3bJ#WNLE5vn5fbPP zRYNjFpX=4*t86GuadHVzRxUvMw&sM-)ol_A(Gx+6T;_#e%(Je+Mtm$ctTLmq9Un7!=_Z{FQQI ztYEl_?{*5_*3sOt=^#tSKjr6BFKqH9EvXHfiA zsiH1tOU|*_^I=Wi#L-p7k3&BZJQkLQ_33|v;Wfo0!h(DAHxwc+gUn*N?%Y&&($z#% zcMb)^FVb~{4C9wDuDl#XscRkp&vfIuIiS71g6lkZf95Qy7Cd6h|J}~Y=laRkj~`hE zwTr+{h{Y?LC84woZHLmypVlr!p0q5UkQ%vNssl<0$m^Zvw_Co0?;Vv$c}WFpEX7 zBU{)bbuNAUzH6um?c5Cs(z7Fz#}}1K{N$S_vB%T03u-NtTnNbYj`|I%Y^?8OH~t*5 zWPrYtDDz0#y};FZ0;fH~i)+G&b$M|?Htm%OUx|WqKEIWMAuKvBm3FDAjI^Z;kqO7b z0`k8hWXJ77>)D{5n~1QJ3&KNGD&@)RFXFwlm|9REExj$5;)uySTGp7N3AFuf&zJ>i zw473ZcK2Zlp7T*@#N58v`*iU|ubmSRPwwfPpD+&OxA$@2jU$_G>lb#B8_IK^3a>vU z1eY_6e%!9urGNX6pOAJHHT($yjnX;O^0Zy_Xpsv%?ssZFe9xG(U3sUBJkH#xd@do; z&Qf7uv|v~`oqQ%&#QU1|DBhj7dZ;$`*W{%(?S$KTK+p(*?g`qQ3>jO<`tdD{2^D;K zI9B&JLWK}ZzLScQYAe9*vY*}LXqC!f=xZl(_WNtqhI%E?r5LHN9dR8=Q#cbw(7}lP z-YTUr9a{wp%HQ3L4$u6&MLG=oOKnVGDP8NmElUr*a1CO+z_F49u2PoA$1r!nv6%{F zLH%KT8SPPWDWH8nHhdSk6JkP@%@Td5`KGvdZ$T(lz+c0A*uQFq59LmQrLB`ND|Jd0yP zG2Ktj&I0djjOmkZIgS|`OYi<3SG3C@RZbV+&hXD)VzG%WG%4S4yZk(etv5gw!#R6B z-pOv1J92BB;Uw{>?}*ac(YgzC8Rpj#VOSN?md*!CbaY90(dt6?I1snGh^ox;&nQQ^ z*kg^?Q+Cv{kxCwG{3R9dg$F46wOePo-tg~!K4k$j`e1WJVvwf$KdZo=Pcj# zP`RJBSI_*nVv%!B`UEZ z!c)AeSG>(R9TGA=b{{JceTLcH&tS*=a@OIOTDRp?Rj!?G=U(5dxOhtE0R7q;`Js*_ zZ|8(0q`uLGhquqE-CS646tWgu7@oE6&U{t(BLc44OJmUNr~ z^k#6ohlK4&`~1M`&%zIYq8PNm9z%T-i0DX!*81Q9kV}2`DI5-K!f-7AfN*|ye@4sF z`~ZObke`rIZX+ll;T5I{}8qJ#0)H*h-q%iDVWq~I>2F~)2($cq259os} z9stypZ;?{;*JfIpCo=`XV&xFjd38t2IqzZ%!%)(eK@1zAkdWCiMbrBS!0dnBT@9C7 zze2e(oA`uK6C>uOi_uGa)M2d{iKhnDY7z>4AH0MQ&hyxbbwiq!>S!mIvKP6IDTEmg zXdp9LTqkPwvFJnY_jpIEr3W+lqr!c!4pde?%vYwfwzbi5J7ga4fnykKJ0777LvHU@ zH`D|8)zacG-WUvT{h^qB&!F%VtZ&k2{Fpi&&EBIOktM7nVqCwWQ;?&kHPfS6?*~BD zi2ULOJ#WbhVZjJmfKXG8bxX=ak2<`tjYXrKapgY<_~<+z8(r|#b!UIMMr3L{IS#r2 zw9WiD7@T=$jel{=rU`Zr=^+%T_MKwPaCj<`H(cGC^!7?I57f9!i)T3^J`q)3VE+1a zjqFR$RdItf1`B`l73q}exE>Acuv!2Y!F!+U;s19;YRaAVg#b;vrI_D#zrWA4f4zON z`5foAK6-L`kZHfE{Q)p(Q5<8U-w$elzNf|eWD_BBpcHbT?mp*fzIqg6<~9wDm@rjz zxBrsWSmWco^jD!wm_Jk1hm&A6uwsO4<|5(BJ#+Q;&Klh0zT5_G%-n~F{yY;cQy$cGtAB<@XA~{T8Rk$_>QXd5&N*X9 zHjCMljQyMH2f)wDwHrlimCEu&=hEengYArAArG@N(Ezt{Pn%^H^}VE-G=ASWO{H5^ zt(W0b4x{pnBjVHU8GCX#%fC&IPvE)XdfOV~&33deL?^EZ6$?o(8v6cTvKTC$Z#hJS_2|K>;g!f0&|P^TUAnU%V~GS;0V|01y@2ZxMHQikgRU~7{Oyp`J|n%pUs>!{j@ z(b+hE06ZVb2d-ooOScIm^}=4h7u-*Bo(uy`L?FrA*p{wt$G(lfVvH-UH2)SKvJmmK z(%BxkJOI|@{~??i`r_%ahzS61op(iN z#)AFWpk9kwsXZS)gs+e@*mq`1YIpi)`S0=GF&6ujuU9_5?L{+JBet`)sj61p>VhDz z$+k8b{`e%B=y^GQm=x#B)8F-Zi;2tO_Pk7ld;id=D$NR+~7h6ARj+;Nx-=}Q^x9smtT6R?0R zj&EicZ4$;dZuvz6C4Qc^K?u{{!_Xg+y&u_~-YHWmpFE|lI+OQ7F&s` zCip>lltCEpm^G~e?I&0$#^;Z@>e{Yhl=R)OD9#=w!Y9R3r%3mF9fe+XS*(3Fkx>HR zhH=86TUcIVc5Dvn-U@@Y>wL?BhlyN7!@~FyZ49LVZ_E(7oGF;Sq`8 zUDg5%EZXP{3gI29n<@Si=UB~Awy98@mmygbQ~==<<-Ha`ScyMRm5QrUn|L%l`bO>5 z``>+}>3(JeYz2be68>yPIQ7k)F`REi`a#sBJ5Vw~HnAw#R~%Vf3I$>jEC8SF(9Aim z2o1A){FiR~1Gq~$-6=^yIbLJM6WO7g@%auDUVjcoWSB?V-;3A&(s0f~1VnWBICiUs z>lh3DBj_x%Y4W%{a6xc(G(K4i#q{*pkpS9UD477fxVvuz^ZkpgJho3cMDz>|;{;V+ zORU5r}Recdd@J`9CvdDu!F9XDCqk^6oHA zH|$7G@1Brx&|2$X(P8Hp7k_>AexEB3uQ(rnz{*5t;gkwI&nVx z1zK*7egJI1VUwmmH&|{%u64t*&e-I}WG06f5^WaJdwS5cEDVUaJ@2bVRYW1W8*yW5 z5mJl?o-6~0xiV1QS(bQ_bk8inGK&pth)28{kLY?*)G7$Y{W(S%QP=Ql%%)KOZeRO0 zJ23lM$-3=q96z^dt-JN4M?&_ktPELG?=X#ltykq5dT6zlwL5t6&lr8mPESJCx5job zJX>jip0Q!(sw~P10d7GmaMU6XlDTi!Fi_nD__9EoAQU8yTNyhSZnFV z2~}*5qL^g_M@3hCgoZ`(4(a${A4k|fjS1SFLcp!Ma}bjo=@WqKOm^%qqIgkF+UUS1 za9__mpr5ACGqE;8AipO42f3$z%XZ>%-RY;cUga;f=WNhP)=S|0t#n?}(4ajUbJW*t zHjUmcY!u5C+Yn%m$1mT@?wtJkUwq-gXj{qt;#^@3xws`nhqK#=b<0ZK4lL63F}f8> z$i9-`SRc!!W&NeD#ft+hB&Al~1&)~1r-Kl6U+6Pzz`GXhJ1^;a=_N#G^UxE1ekvj8 zu18tuG5VygKiijAyjkkJUttOQfo6iFA37n@g?U? zn99+WZ0HIY-6dJ)`~h(A-nNh|_O7}uHN2Vq`)zZ}*#2CiLYz~PB_d#kdZf2zH|JSH z$^^%RqX2*at2g3l<-X8a+@-8H#c?1T;h&%V>I{rm>^(i2f3%KaEo*O{9mL{sZwU*qF4gh5*waZr3zoZ>81l$V#0 zgB*QCLkhHJ6y><~;Y@~hVu(l7d38VB8qsl)=; zbUFxo7q-*aV~7v*XB-kI`lo>De+GAcsV^luNABDKk)UpvaErf~V$SxWntJ=^mELa& z|J=>S@MGI`NAF!J)J4-QD@xR&)N3{+1yNFPFn$l`Wr|Y{<77TfHlr%nsldhjpLoJ= zgbmI))J=^uelmsDE+b4j3o-CT{y+IHj=*0MlsvQyCN{U^@6?+wPE17oY!LUIVF8?0 z8GWJOXgG~e#bU~MYL*7r9S3f^n*61pGQgi&rME2|_W2^b!g_sYm9dT7fsYx6&PMOe z-{opdHnjHGoh(XLGTk|M&I?N!HdWl3Dhq4rXnjJ-sQu^d+_eHrAjXJ47LTOqMo6Ef zt!RJBFTKXXDjSal_g@<$8Sf(pa-Mi|1{u4HdoZR;+SXO+*(mt2MDDEu8d~x>%e-ob z=8+Jtg{eOjb9FppTY5QyD0#RE?q2QwjAxDQjUNZhERul>&UCzH7LHZgPr$J(PP4&) zk6KvR2IKGJdXrUTvfxEm(zw&|j6SUjW*t8xsoHdB|9u6lvNit+|0>q_soKq)jxbG< z7)3n{$6iQwJ@6EDo%^1_>quRlKufRSD9vjeXNw^0;T@vB>eZkAeM~kX9`{=Zc(~(8 zpMdo2Z^g5`(iuVy9G40WfdF$*FJUUGez8+)I5K5Jb2&BjgIca~&x-uWsUI`a{s9nm z5d)H$oK*Q|cPw76w5;*%({MfU5XIXbra-UCE!4BppIAcCm7$yd)78v;dsk<1K9B5$ z5_Q{!ez8dLz2U$>WGI-k)>y5>Mcw87fQY!xQP^_BCFDuIDZlH&vK&*mmiWg|GwQUT z@MN7NYAs+@d)J}KnYH$PV+lIN^M4EWz%B|8jY>}s$z!X2Tjf}38P-8u@0&kPy zNa5tRKRd@|B?lQdCYM2zxt%E4@*yNN`%AgE!~OVp1mh}pTz|94d}fcw?Bt5q%*`vt z4*|o)99$pF@CILAZ4!=lh>Aqrv}Ik`%EWppX{pEl9YKtBsgm2w?73H(EbJ1!3n$+X z_l+ikWX6~Iw^TmH6Uz(1ikTJu77Boqd94QIJ2u0Bz#%m(*D`}< z=n+KoAlxrQT%-rzIW{JrZT@|t9_~-L`w^O0f8Z~p-rO+07X7Bq)$MJ!5JI`R9P5xr zb=|lTNP94mCb_%byMCXQ6sK|dqtIsIviLq_{YX$*8i7~aI~U8FQ!BDAf3TNv!A3Bx53odRvm%YfPaQl@ISEw~ZqYDYkuay{U3N_dE8TSQd$PL@HNC z)`H{vN?P#+`IrnjUnVru)$8UW&W(3R$MAg5$T{w%t{@?=o{s~*;VMy>yZPVr z(@=S*A%#v_zh)+e_X>S>D6#HGaVpwzvmUWkz)1_VyQ)j%%#{p{RU*igpA9l#Aa(P# zSKTlSc#7zYfu)f!3C=ee<$mtpWBPquepkNx03h7WaEx#hGXg3EO4(XdYO7DTQLwa; z3<|79{_V(ST5GW6e9M@;kTg!OUVMjHPgIc68RcjeANSMXLqb2zT%$tCg=!#^^hiFc z+bj*GaXD>7gT^i(LRqwp(cH-*;)0GV58Gu*L=Bg@&VwmGRZ$2NbopR<(Kr0FYOTtK z?&;h#CV1m)h5cS7tr5aMI+T|dolQl~)h92dFJIVDY}K4bMEXfop;R^ERFQN^2KAlD z6L(z4rj|=N^d%^CZ2|?BnrT<^6^M(l)417Q79Z3dB?@dA(CJt4)t#p2MqETh`SJR$ z-^(#uIWUSbIPxk?o0-S~fdcCffI5xkc|XM&x5X9im$kmO(HE<h~z{0!oLP!@mUa5-$s%?XM5mt%?lgy@$1CJXIOp(X0)-Q zy7PgFYs4RgPfS<>{wdPHJAb&S-ud*zg7>oDJ~7oL(oFQR(&2daR3<}W^!71L$NU1T zZkiGxBwwl5<$XJh-%y+T{PznXV%OP;d{hVGpgZRo%GAHoT5wi#-+35Yec5n{Z;;ZP zOphSYjAWrBu7}d`*{*${RCQq7?IlOVeKB}5dL=f!z3~AsK5T5$H=Avi)tVg}COp}y zKL>{aylkbA;*u}xkn~CRB^B>_$FIxJ-bnqy{t_G9)&>pkBsea3BgQeTgT?%%&3T}R zz&7nZ^^uz&^j5B3v78GWy^;q$04l&B#R_+uDdfAY%o<94r))Aezl-&;U>NiCaaG|o zRI_KnW$g8WOuecbBD}lKh14uSVDwG{QBMy<8pVc~O7vdNUIwpoIq118UN#G30i2vq zOq5Vj#{c|4c3k2z74v(@>Td7TFbn#g@&N61Ful0-nhB+~s9h^T-Q|d_O3PoHm+qgx zIX9{)(D8;`kTv2`{m3>e4A9{Cy4z1Mtoa=&8T9~oimu84Ulvejh;x7-fbLRI*VNhP zOYsA0%lm-GzdkoImR~REDetIj)|tjUo~`JY2SD*0_?*}HE=g-MXD6d_w8FpISA%}4 zxZ%~239{FU&OIfYCc-SUnH&X3&ER3T@QdSkD9^15$}J(qyB_D#xb{w4}d|X z#;eJ+2Y|G|_9oc31z_6X?}3FPIv1x^yx&YqKNmV2^I$<)GN&{Ct%Ics(e;1)dUr4p zp#pw>y?W_}WYQOk;i|_S#56bvac|@8zRv|NkJ%4TPDS1@PvrxoHsT5QOvK`f){PY| zrY;b5nnmen14p2*%*DMDG&(P@MPqYj_UG0{XdD(H?gHDWg}*>XaotBZN!l4KHz0U) z$HYux@;y|E^zDI z>khkeG76>nRV^n|s|HDjaPyN9jJOnHvhO)4i!RU*>|afzk}}uOC=aHTLqZ8wZ3))3 zZr`j1_dHHF&nrm}5p3EQ&Nt6*<+``H&)dXyf4(z(pZLl|`qzxeOk&LNa8+{p#%e=F z^a>4PCda5fD*ID?X%2&#Su|RFHukgeaKQn!MT3n#+xcyCp&XEbYpo)Gu5{BA>Um%6 z=Iu@x@$Z1Ahbb=4m~-j}zove7OIoKi_=U;FY&J`^Io`SHrlF^wgVy!tCB38c8VBzv!TMe% zozexZl#tqXn^x$LpRB;)K+DB#sC&r06BO@0b?i>1{UhYOAM5U5Y3%`^&tW&{ z0ynb^@ysWGJOoFCD|glxM}1?tw{B5KiDq0~Ja$oqlAS?&s4xSjeE!gSrwNr`vqSbw zJ_P-E#^hwfTQ(7w$3ch~p1RiDs4Q#;Q{TyRNYRL=&cwCRJ^;!=5XGwpK*%rdZbt&v zy-O*Si)|0c>SLsz<>vN_wOpP zF3=M$aRK-}N3SY8Nn~<304`>q_kKvL$~9->v}y;g`+c=*1#e1RnLeAV`0_2ELH^;j z5dyEC0F$QKY5A+*=%Q5NZBSzL zKPOb2X7J2}zmk&gE4nsfNE=NWbKB{3hd7Q+{A3M7+_R58rZ_eySLv&-*;z-biWD~Ct~?tzevgLptH@2&DWyUBlzsk-NE0=PAfv9ejTMT?75*V za7iaS7`Y`dgPy{FJbW+S-Vu#yzE}3U11(<18C#n-vul^MDBBowlZd)1(5E95t^HJy zi+V`&k=%N3d!}sr`KF(q_V0x}*XV;`5pn6xiypQ+g!8p~Ur`WuyOWWXj019?#44I= z%Ts8+dUv((j%3Q<&o1ds_IW1TkgP(b^b5;D5YhInXFmhk%5d9g?4Eu6PF`N1$mMq1 z17O|;{ZSy>_q}0dK|&|GIFz70p?eUjF&jkSOAD zr!kLUY!;Xa7#7q}hTD7Us0EDJ+tdAW5w_%PgZ{HblI`g@dEuBQLWE|iP7)An1P$ve z*v|-$%;9r+>-uwl=63Z$-*gPU<X0-1rSqtL)R&N!k?@Nfm_h6`57aPaer1rw%$x&y(F zyrRuqEeReAb_@@S*(ZrkdHccGH@aOBl1~v2fcucg9Qa&+mf}{`8DVq9aCU9`IBinf zRI#JIXnNMNAcuLLl3TT;M_JHi*F$KgeWB z6nY7RA^Rl&=`Hs)p0y0|z5180`jf%le5-qST=KebpbT#5NvJ-Va<=IplbMjg8HZB2(nl-w$ zQx>~3s;-YokFx%#A--nm>uOBLS9aXg=rrEz%+!2)vJ^nJP)A)I9Litw2a&v#Rp8-i z%>QHkG;x-zqV{dn8|v4^ucj`)PEp@btnD0;t>5b`%t|At;nvi!4{9qz9$l{Y%Om4@ z(e7)vx_@S>sfeWITdfT^#?(Y1Lz(RIPKmr)Rv7b717vRDEoI+qv`yNlnl)lrybi}E z-LD~MFZissk&WzM*3dp5g%(%VUg!qFDzgNyX% z5K=$Z+951q)8Zvpn#Nn}CJPgD70zB`U9;pz|CaVNy-NnB7{8#4YSj$#-T70}_aMXp zw0?rMh^jg`+d0!@UrI$?O>IgZUY7!(M9f>5jy>&ge1m-2kK1wG{+qV4%81aybp*ad z3l-%B$GDq#`6!q5?R8%W>jjy zbSTqpt}^IhAQY!r&vx;*mHD^PIK`~--IMRT*8Mtl4kK`pYy$?o|8+4_6XQ;hWR8RDhy)w#^Ql_6wH`h*b7n|;gEY10}*B6+JY^2zCEI26Zy)1;yJvfi@B zRrxjRXHT{gtvz}=&rg+MP0sA zMDoyPHAY+k4x(FS9*8{2H?T5rZ_Kn!z_vdI|L9z>8G?PbX!0_Z#fcC5gv@d_hGAhG zY9?O^^XfsYk3ZZp^u%m?naDd7R(uhE05o%i+?TvQlYB9{Q=vOE@mNQJg>^G+B(`DF z)4?G-dC0{L-EMAZh-D+Dp)$cM!=M@{sWO3&^+BF`_5Aip3qQBDw}*12;I!Ay)qbd| zpmku{bRx7lE&Y1nYj*9{vdA8PX>iUJF#H$*NFcb>2 zwmVf|PhfAMES3LK#---^tJI$!LQUf!%UkK)ZS7ldsJN6B@aq z%2_}idBjQII$)6D|VHuH?OsA4(X}Qa( zW$C&S^K$TTy~{Hq0&rk86QRwHI5%=pvpQ1Dk!*LYq(6|YqngIt&Yct29V9K8GNJHT zp7R@*$gCDg(oFk-e?}9cq5{%i)AQ4z*HOr1PcG-E19x}gisP>zG#}?rGHA3#B)7o8 z67e@B;)K6-BmLASE(jwY02DN8lb6>TqXI^(cwfwd-eP-TG<~`G2(;OKtn`U%y*PIy z3=?N>^;v_TXeBwDI8%dP+YTS^OuH*<7?~JNI|wMNsGlkGUYnX6zhq!9u7;{&h4tRb zvu6rS?etC;4q6@iyRUP<*jwR5+&8uq3Zk}tr;6VpBqhzh-miiC(>EA!cXPPL7Zqmh z(c_NI;-8{*J{Hi?(YoOKLDxH64H2V7?y3Yf_~v5ZDmj|9<^fBU(91tvWCt*6)J1-4 zficfGSAD4*meG8OyM0^dGR-7X^P);z$3#CAs;XrxPxd^aex=AEAMqSbrDRRd7V9O- z-}1iUF~YH;)WiZVts?<0-B-VT2#9wucB3>M*nvs zxP~=M3Iw3A_`9yU-`Flb7VU?|H!3Nwg8I)vR6S)bc&OVr1|_ZsdEV8{vuZ+^7}n)cuf%^&}!z}L)#5|V$?4B zW%VpJhnV$Q#UP1f*DHpeEZy=&^uNk&NRt;aigkbHs;0%{_lCgswwF(eO|h~OBNR)Y zC`36E)Sz^P`fAg8HmMaDP}EMK@_Ym8a}J6&A$4P*LrJd6PujT~NJxwA7JF44U2=70 z#jnNt#HQ?Y+}oD3hn9}lr)lseMwMi|-Mwj8jc{KE_4@eKr-}OIX)?%VNXAi&2MJ%1 zU93cu&D*weR<#r^Jv*#|6U)AK?>dw(*_E&KbCE>b`gTe3AQ^&>b4&=Aq%U0suj>zf z`TfwlFlXGBITq%x!^7&WvT_Iu?e*n$KlEqWPz8E<_KVu-=-&qqan5zLBWo1CIBe0n zNOY~;PD7tR%CCsV?-_y-b}#Ft^;}!FT&J_+nAn zqZYGuc64T-MNqvcmWOSAUz`4FbT|5tdV>dERVWFoVuccvkJ*h%tUr5*2 z`yY)KAp50$nM4!uql(#T&JwS15SZhmwdlf^aU<&N7kMA|#$)@NN2%M2dp7qY?I`*m zHXZsrO$CG$o_GKpoHE?wX_f~lSg|(z^{@7clvxOw30Z*A-n{CL#36gn%vwm?r2V`MAt5phsT$5XuI$Lu-lH2Hm^C|X)3(!@iXXZ zv`fp?5{pFEWkI{_(z-n1JQk+tp9oRRt8fSG*?s&u1;vFVjDS zM(4RUK2&6kdi}u4)v6@-oKB3YqH&F>X=+U;pBF0vVL(8?^jZmQv zeYQW&eR1}SS9P^sV>Hz5Y09wH#w0(DKTI4A?Trf`uMXu8j68dWhb?CQDZH79w=)Aq zu;dOjxP5i5?G`&Hvl9@Pi*l{~+D~{OCts*PRk76=AJeTDw;T`FFIfwICk(AB)+f^_ z1-gw9xNQN4C8)_1>C0qs0&hb|1z7wt%I80mn7z3=eCN-0e65}kSNK*TbpsS;HMb|E zDQx&cf_H?4OV(TL4N*wam3jt&X3Cn+WL_vFSCJ5U@VbGF zJuQVt_k6Jr}tU=N_@zpi%P)=f=>*x8#ft zPx!WvOJ8i0sO6KT=?TP`5}cS@t`3wKtO{A*E-kSR;G6t1d8|J!AXf6LojtN&ugR6+ zF9F7w%^tX3z{uqmu9ID6E0{XIFy9EV73eM?pK(fWt-)$49TXUj8z~Mg+Zc39S?p9= zJmVk?(av`}^gh8D&m$_~gc1!v^uC1>p&ng8V|1>I)J zNqzzBt15a1@_&ec|J8rff~PAlC-iQZLd*NLv^H|rg#h24b^}*<$gQYgq9b~Rpl~9w zVL4WjO=;*)TXZ0%TJSR<44yi(ombvOe!K0=QwCqx*- zUF4I2(!g*2>;(&MKH>qqlYT<*!l{^;vNt7~DpZ#5uB{zn2QXTOKel6?7*>y24{-_T zzMWOtySf`GOjA%=p4!@^*IRzMczV1uIg?;W`WZ9JgR!J)VztY8Pq$i$B66)|_DCQ~ zj3s!5@EtB&5!K(J0pb^8m~8PV3HP>XSSPagh0RT4jpw&u15EO5IPm57X%#X_<9i_K z>WeR0XbB1WXp{L1dym*R+ufsEbplyjYnyy8haiSiA>S6?v5U%6jXuxuSM9Lf&7q}d zuAbpMypXM%t{)S-r#sA1vd)hZk@Q-pjCUdw*MY=bD7+PyU5n9q`rAN)e8_5JpNA$3 z`FQAEm6oaIejoFu;PB+i1j(l-T17iCiKgA6R;T$;Yp!q7O!)$QGfg)Nu@_5ACG|k_ z{Yw-vyg55CF5JKuQ;RjB+`Dm-0&j4?n4jCbBK~spy_-2v)f~g1@Qa=ofk;C+2j#^{ zy|rkl&^wuuDEZKVx4@m4L=_LqtSijs>LuAQD3HBXVDhXfx9}6Jl0Qo{>(_8X>=Wn7 zV(3{(egd<`pZOkpkh&3P>W{VCI2=^5URqzgNl^~cz+nIN%m;1PLC3fLh@;a|I^K*H zs8!Q!Yj)q&k2~e!`8^-mu<~V-sw~~1Gr4c!th(vU7c8e$VL4y7G=}y^7xpG@aQDfy z98Kd{>;icg6Q<4!@p~go;o{`XzVs2uN_#>nRg$>_Eaj>8@cMdgZsqF>&DcJTI<2GZ+x+(TZMXGwL&GxQkvP&a+l__`<@`CZ3c1 z{bsz=i76py>XK}(GZa2^k$yoXu5D`SUb#Q3ld6-n*r=~JcULyt?<6+M#DAm+w|a>l zY0)!pH&Cs=ep@|sdwEy+?<~XX(<*Lch*L^I%0d9-yH>YWF^51d_FHC?cr&a4O0-+z z$I{e=EqNU+Cc;uWjuzDKFH;x(^e586pBYW+t>Q?Xw=#Tn@SO5b%t*#=1$@_&={e)N zGh))h)ei;uD)p~_xKhV7uAa_vyxg>}5=}oO$1r82TN$~Yo89NsxpcH26T@P!B28g@ z8SBEP;=D?C4{Mk-vDRn#-f#pqZkVZP7g>KZ1FEZ^-;5bDT#CnfYa^n~-MkYt8|eok zykK*e0LiDKSug11Zs0@iL`h_&!5|*mi!Z~`ggytKw~5(AhL-eE_MBF4aK5~;eA ze4XvZHt8uZp3CkqAyW$^b)e(zI#3|4Yf@pq2+x+-9L6uOXKZ3(J=#~bnQt2YyAp2A zaauX#Kp$fU%p~An0Peym!OCsS@znO14)6%_jEzgn5trvxs%$)6fd0u@+ERgjT`XoS8BF zhqVT+t0Q*O4+wpZ=#w^?cP*YrTo0IM@HOgW zwYe%fJsF;7O-c%{Qhf7@aKSj^-!#GqW1h75&sOLZbMIeBw6kZ2ex{wEwX@PMHLJ%F zTiGX=T0?-ue+czH)z^4$P+RM0=CFVwc|uw5<{M&(NYBgaMR||JyLtZr;Tf>i<6`y} zax`$?QjQp~;K2qoSjyrU(j^YZ__KG*r zA5oOhN|TpUq`sQ-#FG7+N0Mf--?m%nh75<%7oo1hLh$XCg{s@cHrxT9Gdbp}T59@w z>#3#!BTFE$Z~hgLy+4*KrOAfy#79nXjzxUuB9xmwX;f+`V3lXFdkdviW57QBjc|Vu ztl6SVnOAEk$oL(74R`FZ$Vtu^A4@@ z&$8Ac(lt0OQC`C3ZSNtL2=)@M{l*+%*Eyo=a%g@qhs2s?q^hvYT048W{OM$chSy0X z?pP9gfN@#;9-{zs0+EO(80WQNLngw|ZzWqXU6vP#CJa1lv32imjkd_pYX@qCflN#|>_ES5-ig@Y5BPndlV9V;Yct}+D! zes;GbzZ8~Bgivv|;&|$f-JX-JYPwCHlLw2w!Kqj_vEn;TNZQ?$-#?VOk>F9z&qCi? z=d65TWp8n#-L{i?y2r#fy0Ji1A0~aN~f$q0v0bqf3whNNWfrdU1}Q72 zSC{4slfdNHH{x6CZDeT+Z*Mdr&qlY?<`R$Nj1WltPvcb&uk@xevofzf6Jb z1*ePjp99=pYPbF%y19upNnqO@rINVGL_JJ^cdt7Wmu0wh6*#-KC#J8vxwQ;NB6sB3 zSi#ZmblX1y>mC}^Ai9+55!=gYHK`enXoeM7o;G0f?Zt2EJ}c3+OT9}^)-#2T-uBk_ z`z~!d<~!CRHMDpe&Ls2-y-(J<<(J@bjx`(jwOZSyjQ+D;3zFC9b-Evn^lL2}PSYi| z*OEI6d%I|(h1FoW5`rV1Wa{$t9)l#-9;2(pcdGb$_84aoX%<#+T%?KvNYJ)eC)eJl zzR?>`@Kx5Kd1-rXuE(rHV3zJkA}JGa4Ig&RWJ_yuR_0@8dG>2U1>BxfY_>hap2ym< z!{D;{RjFPweAj8+{JwjYR<(Xu!g154hU6Y6wzl|?yYv`lYqRHdhvRP+w28?ADW^jhk`85D3oN+NM>P)ovGBFH2jg zFvVAk+kWWib>9-{SDId_rda9M;ydjU+e)=df~2EH`E$#fXc(8(VNJ;B$gwl0(nk=NYWK ziwoOhZkHN#@td>~S>`4J;ZIGU-p{p03k`vt33B{0(_hUFwOm4)a?!5GOJ(BCGT!e& zyq3cG&Xcd+YIA(6%rgesqo2K!zmcrJ4eR$7x~+uT)%K@#p;_L&(rHO2$iFi*U@x&C z^{m;gFJP4f+Ev;#i@6ZnzUKp}1JHWZVP={cuHm$~lGfa)n&BcQIQMki!+>jASyo>d zNhY22z4iGMEM0jubEMR~Z>Va%8)&rx)}A1bRr_|4aba$-i+Gq2`^f$x4hiZ_R*S_K z_WmE5C%)7#{7Cw(z5G}5zCxrt1ShW}BN)duiOE9B7X`3cPD2_`eYp0jStbfFbh$LY z_4kYGwUfGMU3cPd2;NVsSl{@6RQ|x5RgYP-irLX5j_fEBD9-{WVbiF|sI9ztt3_er zi{QAeXUz~i^iAQ)|#@#rnFJo*(9;-A~YW{+uJNnWGD>BU^&KcX%rW1l>v`XI##3+ z*;#3GYdWlk9Xi{Lfte(8(kO@b&#!K4(xFO@3WqFoj817vc#56d2yLvb^w-t3o6oT6 z(f#Rh%!jh4_n7-vDX(~oRMzcex3)5Pd&A6s)uF}3;r{?>x`FM|o2_a$8qM14y5vi5 zWe>}y>15?%Q_-KXkowkT}>Icf-}b6*+0^@EWQ}b6+`^|bGdR4;r{^FuO@X=SHyZSgx^D`)4m!>DEnTY zD2jN&-je*v*!~=P)%zQD(R@RtS!%Gpn|RleEMzufm~I%xcm}jQDP^kYu|}eKGZK$0 zdEN#(AYVlz0j(~cD{3F`EtM=DG zel^)SAY(^Q{TS8ZyOvo_;7a=X(lUP$B4$@Iuq1)DFnWDWOA|*a1zQ_9X7}_J3rq3@ zCu}{)>IEsz)WU^R&<^9&(gROQSfsm+=VeP|JLS(ifbCZ8Z(;t_eM;pwAvuN&e7GNU zR&GI$?CLO*U^(`o+_a?b!VUl(=`?7jk~eK`;k)}(nvBu|BN;E|>~n#z4%}b>DRs3| z6XGFn6q{5;8*#zulk4kMJUMF}?yD4YH}2v_m4Q8R+aHy5Q(66@7}w>Kbi0g5F@ku& zKGmF^nbiontC&`LJknc8h87Pd-RgRv>^`^|{At>5iFr7Xc?7&b;RyTd+s5n_;HHTj&CPdM~WzbkenY*H&!yMu7#|Q|S|Yz<3mD}TUF4ORFnE#{r7YJLv!JTpOm zZiv4t;oSf`CXDoSVa`Y6imMY8btIFIO5JGT@g1GDtk*ARsoAl8KT%E|84qLXjCzih z=bFP&@?gEOe=2p2coHe(uk+8iuW|TG;s@0&Vo6_q6al#W$Bt{` zDpQp`S@iLgYAYkq(Muip<%ViTP|46?hE8i5>+P2Mg93AH)kb+0t!m~~QrI4Xu)Uqp zPCUDwSMdW%7MhosiMA>7~-*RuHk089IBl`MiR%M$O1`VrQ=g5`EQ z9ziFe>OHIOa$H)(VbXiYMtq)WN7+`o+FKDGIO|G_y?{}gNXN`~5rJEpZK_+v_NkPx zCu}i~y(=EdE7Yl06sfwCc1Yu;PE}{g9mw>J7Vl7-%C~{#eBgn`D^~Ntn%oxVXVYDm zyGD28@~vG4$HX=Pt`3q2KQo1FxE`3Uw@KIG8C$yy5)c%73huDq3Df<3Wb<{uSH5gXHImtPH5hLsUU37*R8E6|>AlQeSd9rmzq z>0XH*n+~DzcS-S{jj34bS`MwM!p>6RR(pBM;Kb?oyH}n#+BTAR4tVM+2`%m9lg<$; zNI?bD4$EU6Vk%)BHVkHnO+35=vWeXP5q2k}?&K zJm7j)my2k3Z)6O1?d0bkzTEotrmcmLj!4C&@bvj%A810s3 z?eHF(;5g>+--X*x@lI^@*Vlv)-Cj7kYfIOM5X~XU$m|aznx9QwZ%pvDjlQ2}Z>?$? zO5fV}jth-#En$v%Gv-Zlr-_3CrBCqouPb|KSds%5!NW6>K|E)Z*BoY=Y%JtKy4?s) zo5tc!atSA|}o9oy+rHmV@e;*#G< z^GDh4XJS+WI&Q}b$EOCW_}%S%JMluw_)mRzC=g$25MAAinY7m}mbUW&ISL7E3gu%| zhkHggyo4R<#4tXf_Qz~uiyL??V`PZ}?j*ByXD5E0-?n#;moIi7pXCT|Ywx3Jvl8lYs6$J!)Sm;J1w`uoy6&{s-Wf?XndFk=#&@>YJJ=R@ z6&$Q*xK0O74<5Bs!nYUa!Im?4cTI;|NF>y)^>{|H9h?xflD1xG*naaP1y4BbURm~A zY@glk%6We?5_bJ_Nj;sM&6l=~h5*4Ghe1>Rt5ZpG)VHRW2bx~##C49Br-ml$s89;2s7CK7ep3E9$i9c}?B62cbTcsJn+;ahhu!0x{OD>9*3{&X(~- z<~)Qduc<%hG$xj;PW=m7RitekmshSKvw&}wR^SC4YXei%mtDC{YULUYD$JPlyEfx- zJy;L#kMEUxk5iE9S7a@Py0Em2jiCC! z<}2f~e8<|$*}>?Kqs#Dq&OGgE%F>H_cn-I$k>n;M5Gc=IyR>&>&=09NsB|4R<6hQ= zv#Kd#-|B7p#{%{X?gvxev<`=LuHQv}c@|)a^9*Bv=ljF!UG9^mi)B!Xxjk#am1LJH z-1dE)<*9o{u!0y-RwT|l3f;B0LygJ@JXL#Gc90c*W74&)VqjD_!Oe2=H@T#xZ4j{7 zqY_yahIz=L^r9~8WQ?4o@$rs>c5zzP_zSlgHGUXZ&WEuwp+B8(PMw*JNoaaeKQR31 zO(FZ^=}K$c=y@WFC=^uyl%u63DCs~S6MoxBALCV!azYIrJpTaS#;*?y8P4X~y%z$# zzxLf$Z;duXb_e!6dH(>vjb0j5EQg$oQZkl~;<09w1yDUR-ke+JAv3gbk3&m`afDp@ zRI=M#Y$0POX~Sc=q$PF{&9`RkF&X64_R270^QN&RUl6r&bOKSvz z+1gmyame{dq}th*p(UxIX!}d5?pHi192|H0j-Qou{v5iHTE<-CVJFPTZiJtD9Vdj+|GZWEAp!GGCRJyaSi_q${O-XO;F6VLOLc7s7 zj&^~x;Cr5Hm7iOhTIjn{&C3-R?cB+I%?-RzD0hyJ${)_Iakr$M3pe_r^L` zt$?NNF%e1Zd02|BG~LQ~Y#KxLsD~7FY!g5^HTCDuE7%Sqdc9(kGWJGIFmO7-c@7ilH}yCV3v`!nX-=3w-|oVU_mEfPV@T_q_o6 zSIg$vbw>H&sy>e_%wX3f^gXGs;JS`4Hc=aaf^o?ee@~HdhzON`zB(H4C_Gtuk)m8A zt8WV!_vKyfc5zAZAX&ov0!cYua%mVWvV^YqbTUlK)8x2VO5w6XASf< z;$AG#X4AFF?TlomOo+#$DfF*ris@Z2zz}#fk>l+y%HzW_>bJ8j2E=7$BkyuC81*gC z3iWcldcxM%;b)nR!uxt&X!0vdNa7E5b%laF7tc~pKnHs1JS%Fqnu_0CpDocyf-b&L z{)Vv9N4jOZnlOO}?qcc}J$|*X;m{yWI5cK3L<7 zM#PhhZga`}Y4@Tlg#pn<208*MEiG1CRSMjZ#_GESFn}SM4&PB;Tw`^rJ0&hzXkc7u zb~2K7MhkV?G0jIVlGe}}Eu~~-{v7as3WHnz-_Ra=v2Jw@B%Jy7i{>;R_0f8dsHpUx z89^c}(gb*2fG(#YfBN+=m2PgMIY-@hB(b@>j0=m)VFYOVWO38$n%C8IJs-qY0L~0| zKxACUjl=8fS^oeLHJv)c;hwc|b0mITmiURcVEK%2pnKPq_+#P>wsw&eyGw|MH>q!# zG6w`!l&3s9Ql`cAb&7{8Mc)+oa_>l#i>T4!KX&FmQN1@F#<{8BbaDdV4z1d~Tf;iV zp1Lk9`8*!F6j3mb$SovQpy`LjM5WZ(67UC!P;+ zUqM2(I?(5)?vE0_9<2(Fokgk+ov0sm$M?TV4_Z|j6|Kxff0U|YT@9OtzI zb~;gTuqelRT3k_z1{=TGq$eXAaYo;BMm_1LZAD=*M?p(L891c0Rv1K#?TlmB=~|ke zpxzqr%({)bgQ{L3hff&hB6w*r^f(mV4$bcFk`O-e#_vkQ*KeiPd`j2Wtft!5PqWx7 zeb$h5f1m)j@rvA^N-K-aW47oOQyprj%H}3cIupYzES7B#yZ9S}W zLR6{yxc;@p+IZ_m@iZe#)EXqeRUk&=V;MaePu*{7v*9UY61;Zu7YO(%+*WgoPVA)9 z(H@Vc!@eFyGIPgj)`m65&5k$*vh;!y1y{%iy=kMae(OV^@n?K=Vo!20`PR_Yd1v-RJnW*@*8CqAH8U!nLKeNCa4S7RNp8@|sG>Oa~)(z*>RLb-=hN7#j9 zA2gp{a6XmQ#-b!q5^ih{lyF=8D}uHsTSW9JP>fckNIW&5!D<<-;ey&c0hPcX{d(v8 zS8Z>q+da0Gr^1=}7UtvSL>|0yYpeSl`iqsjkV9>p2qQl^KKZMz{u9ux{QXk;+Sycm z{%oNB70(GtyY6n%wT~jwd@-kKk}S8)J^b+y#73YXJ(y>cU51}$pigTXCX00*A9RyB z4AOJ@3ewg-EBGQEHLo{5*8+jCxkLg;Y)zhgKN_7^pmBWY^a-X=7bY2R7^l;Z5$c5O(zFJTMY!y zEy#k^6)q(?c}HeA^yyzol0ht5ypIzyllr@~PJMY}p46j)J?W}W<`nVTzQvz9fYD2e z2o#1V1Kf88t=Vc5TRMnbeeB@&`c*OoFGd*aL)BPaO>K8ik5h&GMWjLou@KGVN-{5E z1Cx%M)OvLp&q~bjjr5lHK4dS2knRdT==yrq?H=-5Tf}JGhR+=I_53Qfy<{}KY7I)& zHtE`gxGJCW?M4@x_BVu^yA_gS{{SsxJ0@>(M_Qemr-rDNX!~B3$Y=t24Qk*%gn>PD+}$ z4x=P$175^NFmV~pb}X|LwuXf)!h}`%wK**^O=H2j^|hw4Y;My5qnZ=*6z{<6#d<%) zFNk_4i97~8FQ&r!liWHp%`ARcw~0t>+*-=MbVQAd7jnPn zy%v$gb08(7kQYW?fF4KEx$!hAV5HQR=c9&|EOZq_^@|;2W+B#m+j&v#H3-ZXDYxa$ zGLMeOoPHIMcPp|#-a=H5Od9JgHi({CLZ-v!4t=<;P02Gmw^w4{t$TbgIm_B7wugho zQjF&bKZ{_+1ByR~Gy}zbVe(=X6zrNxDS%SaQJnNN0HjhdB`BVHgYzjuC;1jveZ2SEy;Pbp!w5-zTeRfwtLW*yx zv!iK(XbZ^@Qz0(QdYtkBOfUGo|WT8S>2wKlCjBn(?hq^@VEMGR~PXS_IvAKQbZu< zaU;EU-wHfCBo^{L(-~)wf?FKc*M>BiXS9dTMBeL{Rr|x(*IQ+#eSsKTf~rH!OEiq|r>LPr=ZTOEKLlT?bQ-?10RGpMd5sb_MWW+`2l$B`k~&k0=W4>0;~h#L3-pWc zvdO6G3hAj{oXV0ZR#eXs;PL<**JG<(#dqROJ4Jv=8r#Vfw_96)`S}q22PU`m%ey;0 zGXDU?_wk1N3%Z?d$9xKi~DWDw@rj$&x31r-#?5C&J zxhvI+PCZVV6raR)RuTZpPe4x|nXZFPw2o}&=2q@~E1%MWw26V7{o;GqRRBn~fN)1a zUQyo^RDTJ_sJpD1oy0IV7>5eqpK8U2;Qs)HA=Q&nSg$VRi08__oXn1W!Ty!nSxmuz z?0b6F^{|R)33Mf~+O?xTRiLLH=aonB(@oR0xOJUA{_Pzue%1Y*DrU^M9A-S@BPRzL z=CwcJ1Jbm6*16MTnh7rmd$woFmM1?d_8j!DL`xvD2^JH({iB-B*HOS5*eJ)ZO46-a zN;;7UMLVM(O_%JKYRERCaa-EVaLaXVaW>^ykgu3Kdm87L1%h?wpL*${i|x8QK#I+< z?!z2cH92U_=ebu;v69t^S^UK(?<)M&#e8aseEk~ersZ)Y9XfXzuFBr*L-Kw7rwpLv zuf21B7xqozC}cyIj{Y*f;Deg8 zLgfBe zKYnrdPi%T0eze^;N7bSc`8p<`(z*WtpH{&9@rv5hJUgte8cinfmN_NUsjrgHGn#+E zqa@#6$Geqa8fv9Y40vH=fNqUO1~HDGN=0=p6|#BgYpS^L*0|ezy)s-8(7OKsjb&VT zAI0)Zx(zl28U8D@2EJ446nZo0xuVA`$RgzYy+Eln`^57G_u6yvnzsjnyj8F)vFY&) ze-+pyenOi601kXhD~1}Dl>r?v&edO8!}XDyk~(`GNC?t2kyc~=tjK;@4OJdA(ynEi z8L@4BYTGA)jv0U2$8|oUp^L#<+?Gpcd8}!zv+puM?7({($o_OuAqkBfqB9(Gf zdIOsJ3O@w+3KZIWJ8FCU(lP#Kti|E)20*!w!}?gTwp~g6DEL><&(f4D-<<;>rQ>{|((D|)DdCYKKKd#tV{{Tvw zI~`7AwjC!?n>{gX-{D_K{{U%5yhjON_hO}OQe0(BpyN5{KPqzL*?pQniIT|I^PfAx z;lC43-@5SjsC~SWKb>2L!Jadike(X8Tz`Bj{{S;y{Qld$3dbQMKQ4Yz^*m$Vu>SyEvkALKF}bSAu<2d5_nu7;!cP*r4>wfO z;m=~sf2CTF;Qp%0Oui!1qa(7y#=Rm5W4gMU&eL1cZ!X|ZGFwY~g?UkZcsa+f6y{0U zzH5Rr(`e~fR^rUw4$_ie_UUlSu#H|nnda9&2sJM)MW=}DUSrW`gvPDykWFzB+e>Sy z&8FNUi-;sKNKoV!AKg91abH8EW-}V(vuCY%f=A~3M!$>${{SD(#fNMh*V1sddyLE_ zRbnKXioVuootfaN(NOklc3}A8aX*S+)0-PDVpITj3O}hir%QTtyI~Rjxv6=H;Z*u z(jj+dU8<#vdJ6HqMEHY3)5XS@JTeFfVvaXODC^1U4N>t=#2I{Pr`Y&=L9v=0Ur=*y z@i;%Z1bog({t?Ls(2BUX%Vn`HD(SPL@YRBN_r*h3WIx&VvX3N@lPu$*AMAl%-EuB8 zdqqc>O3Xqj{vvVL9+k&@JJ6!gwCfv4QJUV-1W^KT&fVDkPc_*puB)y~8p;Y;AcrHf zo?r6mQ%^;ps!3km3?GQMXxavqp~U;X-*~dij-oh*^Y|73R^Nq4f;dYNzDEbAdgk@G zmj3|9QixP4X|N@z?iq>P)zockY3Abx zroDcLm?)xwMNkPr=|u;qpbwt^0BDKeK0ddFE)d)$g1bYWcJ4T8^L3MSWB_rT=CuwyS-MRUzPTu=!kjxcF zB= zI`kBZ)dA>E!IAjZmYLzbJ3zFKW{x&+Nm(TvMtwynrk;hlE~a;hHAys&5n5kIkFwro zIZ*!q3wErZiWloOzMG~;A$NB-GB2W!yZviM`%9a|7vkc1R9M92#~*kOt@>95t6nws zt8;t_c*~WG{<*ITE8OAiGOLRAv)VeIW^rHH;rS!Hv?1zA?TYnpgc?SJci|gb%|k}B zySkd@be4JJ4CE;rMmr2wl()!(-o1a|+bQr(klX(NFP9(8SAQ7QsY@=r8&8>Rc=bgctL zms{2y;I)LRB1F5UxsZ&6LHtaAL0^^Asfxu^P=jtyrS(3VYMc|4mWGmQyLgNQ$mp?w z$K_3JT5iTh&3Rm(5M*!DuJ1NCsKZ`AUUr}M|MzndNv^s;R&UnPEex{gi=Euz&AF1h1-W!!3 z--mDOP~Tl!>Go1y-9~0n^2G|AG_Bk473Nb@l(|x|sWLs}+{bRkdoef$n=4+%z)1m2 z^d-18#@}jJ+Juhxw~{$O^2$7m1>Fz3%4b#<43-{hTC`D5*!owQ*Cx$Teaq&s7HBjAImKf$CmxZE0u^X z>NUjDOFhJ&>m_sit3JiwN%3u^;w!9IJFRXIJ`s0vB-%Q#Aa(xrdsQ-M!kyF9j$_b8 zvycN^xc1K!_^g^~79@9ef8YkAf^RkNB6lqqu!G#=_%L)aHuIPqb3=%)>Yz-5#uc2Q-k#(jrKCW?oo!DsX?LdDra; ze<6cH&;yvQ+jaD~KYfA16ZGWQ!sMBM*YS|UbhX*+V(YpToY7NS_`j*oI}ZzJHWpTS z`6a(oB(i_Cv~Yu`72EhD#g<+z(S_1lt%jish;HChkdmH`KiF#UedqmJfVcyII0Cy* zf?{K>>xml;hR!liq=Eiid-bo-GyWdIQp=?2LzTgA-_-Fk{C#?ugr_YZL)h7aC}Hx0 z`43;$HHG8<02SMKKS_e=?M3dZc;$5aHf^BoA3U;uu%ox}9xGlK-yCkk<#Yt+sruKC z{BW9A_?oLONVn5rNEfoia?XD+E8_TP0StCMLZ`yDJ#5CjsL*aZ>|brS;|vBGo&iZgMW>~YD=4W}Rrw_Eb*brN zb4nB_C;Otjuj3bsZzR?y@LrF0_S$`p2CFnDYh6r6OhLOwpn;EGE7fge5Nc7gACO3; zkG6TQojgGlmcBIcC9TL~I_i^|M|R%Zf&8&wJ;69iRq>ORRd*G1j?Ch;p-bG^l4Y#S>RGrSku~%dk7@QOVX|D6vA0-Rk2{E8U#@G^tb$Fz%@0^T#;=8XB zNYg=QZpVjU8;tTfuKE7}7AJKS-ix`J@EgQF8PubH0QkZ^_x}KBWbo-Ie7R+pgA`GBmHWgnCp@&vUKAmey0p8PL!Nv zbc4m(O~f+km(aeKsK@gCnSsQu*e}+${u}rnO+I<`o7gsL7r-JXU$e!W?H=vv+OoVY zrLMiNPvhNJOnB~Y+zSY2#_LOd#en0?J$SzQ+PIW&HZ>h~_4cmQ_PdB%d{NQ0F_0R=$b5giNHxPFVENxODFf+Tc!*i^ z9dw=JV^2=FXeR;N9Pn$g(`6SH#W(VK=DhixTN6g7aP{e1nl7ThAS?kraa>b{^*SRv zXmyscg5olMY~u$3;X0nQtO1!DBv z)0*du>VFV*tq)L|!&>me+Rgs}E}5GV+!5P%MXtNTej^?s)vWZ5J66)|Zf@c;I$TD| zkw`f5i98eO>s@xUVPmOVwVmy>7ZJBCvql+M{yE3gR~2#KO$Off3EN6EQ) zS3L(>>TVK5!VK>8PYn30QL;LWJ}c4Ug(Y|l$U#8J*kRWh;;DGfEh|md?6gCx-D`T_ zl`bzya3X>~;g4@X%ue7v0i@9MeG1CfMY7uraxsyX8(^DTq4{%zpI)_IJvcV9modSz zC4J8`a`Qh$&#)Av;-jYJD9Jm?>`CJr@9b|4+`|zbZP{pH2sR?kWSZ-~qyqO48DjL$7K6 zNd`eT%vbxk=8^?b8n6Y+bO;F~_O6@4dKJVo8~e0hwMe**Kl$W4u{Gac5fukHJGOMm zaxPS?k`>{+M^tMn$GbCnfN)hTqrkosO$Ixw%d3$-t$YGp-Z;X;801ABe}wlv z>**?EF!X84SJu``yYn%r%-T^p2uKmG(egBmSLs|=#@OY3JHz(~#77mx(Xs3ulo9!X zitW&=eCmZ4qAC4P<5l&|Hq%(rE;Ot3cC@-)Sr5+(uicSP_lNSYn!;6$3el6)-R^nM zg!O%=?D7x+>`iZ5LN9gLwv5GYOUO?^M@r7I_-lU+-uZk_Z!8`Bs99zDoSbI6T{BL! z(=67~AN4@)D5rFixA&dBJ*(WrW|X5%s(Q0GAA04RL$cm1f(w#B#c?0B1(n3U7}9lk z)R^?E$Byg$l$3DaKt*?v`Hd#|2n6-O;11ZKl^QpONRntKh{ZG#{L##Zf~-GW*OQiG zrGmx75W0S*SgKyyn}>7emzE`jyo{=#XDo0%j(b;s@M}YwX{7O0(lT2zn|(D|aAsro zGQh8XWFL`LW!be@-ik_}!vUsQ7-@Ua_}( zne<}9>NOjj+qXM_@3iAS*{<1e2RxI=&suy;>f%`0k;n0ajDJJ)HS!sDK3EJ&uTQ4u zr-`Dg!NH$2X{$b{>2IRj&8XZ+2bPc_Wx?*p_(pPltJ=OEcwA^2Q`<^a^*Nbl)Mi8S zLY6NKU24WN6t<*=`(3y@ zl&L?)rz0J~uHTLZPVYlY6istF+ro_`+54(+N4|Rs`TV;bTQ9`My%lzL*QBe##(N$$ zqkJ{-74*@zw;%Q;h#<)dID45rQBitlp(Nwdy<)=3D+_ygqP1ISZQ~JIS}D%N9XEUD zlT>w&7`b;W`D6TCb*@v#z6r7MPNQ$C$9y!MP#}utW{-S#F|P_( ze|<+o(-qdZ+CE{C=~VU2UrF%xklMbzb>vyQd2vRl9&4BW>M8r!?#8^#s=h9cAv_)V z{JR@sY0{}p`(K2?@V9|6d9fS$vVUV{5pS5wf2V-3XS+HwvLgu4^jV<>UFJK4-Rg zs$MMdj+^1AbbIYiUoGzS2(2tF)BSAHGk{3{0AzaA)03QuoH=59k^AHP_oZq~64^X@ z3RBX(GNYi@h>2lAWNZi91{cD8LZ{v~x zisnGP5#GJe_KAza_r5;2v)A;idzbqPl$QiZzcJ$@wR!9OHt^N*htTzV?IKgkq_TOj z=jdzC#A2eQ%OiR+KkQhrM$b_R$GTGTiC6qo3X(LQkd-QBxVldoyj-(bU*o7mJb>PRvbp9vatt zvMp!8VaDw7UP?84n@0($z!ZPaROsIIv1hAV-GwmRF8=`G8L6Hg=%~)ewnXWB6G!GE zN(NEAMMD6%Qe(pt+>ybrIncaOHJ#F>!OAD=UV)}-_BxPKlLUW$E0xAjc4qOClF-$L z!s2v0K#feYY z;yjnMoZ?J+=e<>*!avxT=fgVw%e!d-{?61$`KOF@R&J$-dgZk}3irbL!d%-HNb`l0 z9V_0Wp4C=RdLA826eV{qr*l4<_KIhm#~eyP^Bu+sJYaLpdSAj6Nc=4nDB;X^v+mk* z0VE!^;;{&|%WHev37R%C5j1V{1MB7XUTfKY4j_lZe=#Kg02d37#=M>(&FW(C zzRpogRCVR}6+(RJot5zU-*2d(0lRoCyMPUWkbb?XFGCh^4h}{$RW*%T-$k@rrif2- zaK<}Jc0VZ~e9qpg4SYQ+bE`EN?s}4KDtJ`Zf@VJgvjgIJ;^xUVBUpz>R*OK1d%_ZH{!xxs~M=dL{>PvO4 zKLX!Lq4@Jlxr^k2_EoaHTwqHahXWvSxEvkbYwxi<6HbmAR;c;Xx#CmKWmc+A!sqxW;~U!UQqI`tzPp6l`%;twA9Ye>C)KHeF1ySR9l$zYI1eG8wweT7-@ zhl})&5=kwrc9Q9Oj7#Q=c^o=R9&z%K-`ll#(g?uvRYYryZ5;>rpL)^IW_y1VX?GDZ z5~a$nM_f0`K=xpNO8PpvT_0m*xLEgH<2xIS)0fFerMbMFEv;Ze^UWtj1F-i!s=c%B zTrnRjG6p?>=~#ae-R9A(w9MiwxtXRN*-&Hy>&dSR1%>*?CN%G%H9gdD-XQq5uiaix zZQ;u(^i4fUM3UhImvfKr^YW%~&}Xf0d@=Fvp{~z9h2mF+<4}$>HLdDK5v~w@E7Dy}Uopoelz)d>hvB?(P2=q%NKQm$KT>@67JO)(r7 z{{Ucjt5)DOt-BI3%;Om7x$XMbo_^2`A-nM6F)M1YOv#>peZYQTSHa{s7-I4C=~dYE z^9rtw2PL`Z`rfClc#7gn?+|MDH&Z(h6t2QMZ^U;KY1f_`)FhJT z9Xu?y{%Ou&V}^_#yc`jl^FXZ4xq(nPCA%L_^Xpx|!P_P}hO4RVD-3Zhv~SqR$0U9N zzf9sRHX0diNVuhBtgL+gSyFSwM^^s;BiCD*P=mY`-ILUg*{%!Ye~9k%%S%5C=`y?% z>Tos2rEwYCAh#bXLaaF(iOC}e1KzuvWhjv6s>Cu6=Uz+k${8Z@{jJo1n6I?x%tUng z2@at8gSU@*_#P6WPOfPP)z;T&_OnWpg$HAXiVJuUM5wBuWA63${Cn4`d>p=${t+o{ zC1UaEm)=ZDPd-$Ge$TtDENATupp^*9yn@yN?@=Ah2j3?y3Y7SKW zi&mMg?B_pl?!j~i`@yrteAfiJFvd%tduY!`Ip_8%!(*A26gK5soxp*{bDk^PycKaP z=-N=3iIuEXWXC-R8TyWE%RD=w-Rp9Qw7D7>LEA0!FYe%v_{x*Pd}ji^n?|#?v$ICD zPcF^~{EIX_N`Z`?=cRRVrej94h8h~$?&RdyX;Oo$E~cHk0?;;l*UH{2oh-g7_=u17 zvTAI^fzfN~dvyvT2iNBIuaW*K$kyKw{81@kx?AVR<;8dz0_Lkb_B~p?S~2`t6OBku z0~MG*n63|Sb6tmryj32pXtF6Qbi7wtJMGARN3}pa0;=J$S zQ+b*uoi?Bq=D3W>A;(jmGw)u>plI+sCgvt5Kf=9-(!BX->}`9ab~twx2*7t3rpSfm z*xdoeTCrPnAAEub0fs4Vuntjj-D)MVF?y6QF$gDb1E;-X&oi+sRPE1B^){_@Ff1B3 z+7Bdp`d205pB3p^6edkd^&$iA#;0_R_zLEfoSl)=2&Jn!y*OFOCb-lt7S~U+MxO3x zJ5?fHU5P!1O#9c%n%{~h@$bfsGsLb4gzC1|`enO)%WGjE+Cc2gIW?j2PvTAg0E;xX z(CuxTOwde#+$ewFUgM&<{@^_A?s1-#&iD>FZv1iK>;s?e7#t}W$W{P!^cCx2D0?-{ zEzdg@S|rMJee>dWsK9^o}t_6bdK-DI{=+Smy)MmWJdWC2y@>S~HRd<}01IyIw@u)m6WiQcDaq3{hAy#tM=1G+-Lde9BdD__@opkZ)nr5(`P5rg4;%5X*fSU8${{Ro`8ca(jv!_j_?)h4Elh3#R z0KV7mk9MW|KA~W$_zaEnEQ)fn4#h~|k9y^uD8GT&Y04*4t^6?XwzV9srQF)lpfi9TZ$v=Z^esmGp}(D%(oCxU>6Ak_om- zb07mhg>~Nv?*n*d*Kj94c$Uc|`uf)o@%K*GZ*|QRPqNXkZk}lzT8LvU=C(dy4{Q!j zYpn5xzJ3_^LdxF9!{<`eE#g#dLS8JaWFtR0AL|%)UYV^b!`f1eR_vOS_upgHwLK!! zQ_#((u_PAJH#W~RsyuQIjGKt>!4>B^*;y>*&~M>Oi{RTNafU@f(f1Ep@{bMpV_5Na zraW2WoksTlN!UpocM=`fBR_j*M2va?Ua_XxM+9-ADDvavE;v8uwP7j>i_%(}(521q zNKHDzD4-EV2!=FF1X1#jrFsv-*!F0CTK2q`B>RP~Wg*5+K;pWuhdk+wI)A1~)9AIs zkGr7TJ0z0W>F<{4a;Nx1=hPe+yMK!ZWV*#-5Om` zTin?MH}=^^Mr;XVCm?6kb6$2|QZTJ~5YA|l0Ve~VbLmvu(yGCFqBKr@T&DB z_N$WVI{c2vmOo}?{ws$HtNuTQbeN2Jai}@ro1aYAp8S0`$^QTd)y1qHb*|Z>koH+PIQ&I=Fd%?-lpn$eW$jfp zn+r`}O1RT6;di!|3>rQphC%maU!kuH0gHHQ>Z)W{rm9BPK6#Gfc?el80DNSf*xWh- zGwIT`dK{5fH%+o@=@+1YOb@>Ur~5@XOf8T1v`gCmme zR5NjaI8oRNUHe;dg&-+MRvA}Q)fjgMzB>zF>h)Dk?0QmM%R}el$|KxfJmWjF!1q4Y z)ciTnroGhH#1~K$)9nfS8F7ZWn;08csZo>7cZ0$n6OF{HqWLmsJ2GTXz#7-K@@;~B zmNH}uwI!SWS�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 NEcstO-x2>^{(n-u4{ZPd literal 0 HcmV?d00001 diff --git a/module1/projects/connect_four/evaluation.md b/module1/projects/connect_four/evaluation.md new file mode 100644 index 00000000..c2984c88 --- /dev/null +++ b/module1/projects/connect_four/evaluation.md @@ -0,0 +1,39 @@ +--- +layout: page +title: Connect Four Evaluation +length: 2 week +type: project +--- + +For the project eval, you should prepare to speak to the presentation points listed below. You are also required to provide some written reflections as well. There is some overlap between the written reflection and oral presentation. This is intentional. If you have questions about the presentation or written reflection, please let an instructor know before the time it's due. + +## Written reflection: +In your README reflect on the following: + +1. This project did not provide an interaction pattern. How did you approach the design and problem solving process for this project? +2. If you had one more day to work on this project, what would you work on? +3. Describe the pairing techniques you used while working on this project. +4. Describe how feedback was shared over the course of this project. + +## Presentation points: + +[ ] Demonstration of functional completeness + * Run your runner file, and demonstrate how the game is played in the terminal. If you've considered edge cases, make sure you demonstrate that functionality in your demo. + +[ ] Technical quality and organization of the code + * At a high level (not line by line), describe how you broke out this game. What classes did you create? What is the responsibility of each class? Why did you choose to design your code in this way? + * Is there a design decision that you made that you're particularly proud of? + +[ ] Identifying code that should be refactored and how it would be refactored + * Identify a piece of code that you'd like to refactor. How would you update that code? + * Are there any parts of your code that you're unsure/hesitant about? Why? + +[ ] Discussion of test coverage + * Show examples of a unit and an integration test that you wrote. + * Run your test suite and open coverage report (if you were able to implement simplecov) + +[ ] Discussion of Pairing/version control + * How did you all work together? Did you use a particular pairing technique? + * Walk us through your GitHub insights. How many pull requests did you make? How many commits did you make? + * Can you identify a PR that was made that demonstrates good commenting/partner review workflow? + diff --git a/module1/projects/connect_four/index.md b/module1/projects/connect_four/index.md new file mode 100644 index 00000000..2f37b907 --- /dev/null +++ b/module1/projects/connect_four/index.md @@ -0,0 +1,29 @@ +--- +layout: page +title: Connect Four +--- + +![Connect 4](./c4.jpg) + +## Background + +Connect Four is a classic board game where players take turns trying to create a line of four of their own pieces without being blocked by their opponent. The game ends when one of the two players successfully lines up four of their pieces horizontally, vertically, or diagonally and wins, or in a draw if the 7-column, 6-row grid is filled without either player successfully connecting four pieces. For more information, see the [wikipedia page](https://en.wikipedia.org/wiki/Connect_Four). + + +## Learning Goals / Areas of Focus + +* Practice breaking a program into logical components +* Testing components in isolation and in combination +* Applying Enumerable techniques in a real context +* Practice implementing a useable REPL interface + + +## Overview + +In this project you'll use Ruby to build a command line implementation of the classic game Connect Four. More detail can be found in the pages below: + +* [Setup](./setup) +* [Technical Requirements](./requirements) +* [Peer Code Share](./peer_code_share) +* [Evaluation Presentation Requirements](./evaluation) +* [Evaluation Rubric](./rubric) diff --git a/module1/projects/connect_four/iteration_1.md b/module1/projects/connect_four/iteration_1.md new file mode 100644 index 00000000..03e890a6 --- /dev/null +++ b/module1/projects/connect_four/iteration_1.md @@ -0,0 +1,39 @@ +--- +layout: page +title: Iteration 1 - Game Board +--- + +_[Back to Connect Four Home](./index)_ +_[Back to Requirements](./requirements)_ + +## Test Driven Development + +In this iteration, you are required to use TDD to create your classes. Use the interaction pattern to determine what a method should do and write one or more tests to verify that expected behavior. Then you can implement the method. You should always write code with the purpose of making a test pass. + +## Printing the Board + +When a user runs the command to start the game, they will see a welcome message, followed by an empty board. The board itself will represent empty spaces with periods and column names with a letter A-G. + +``` +ABCDEFG +....... +....... +....... +....... +....... +....... +``` + +Player pieces will be represented by X's, while computer pieces will be represented by O's. A board later in the game might look something like the following: + +``` +ABCDEFG +....... +....... +O...... +X.O...O +XXOX..X +XOOXOOX +``` + +For Iteration 1, students should have a program that will print out a welcome message and an empty board. diff --git a/module1/projects/connect_four/iteration_2.md b/module1/projects/connect_four/iteration_2.md new file mode 100644 index 00000000..710ddd65 --- /dev/null +++ b/module1/projects/connect_four/iteration_2.md @@ -0,0 +1,33 @@ +--- +layout: page +title: Iteration 2 - Placing Pieces +--- + +_[Back to Connect Four Home](./index)_ +_[Back to Requirements](./requirements)_ + +## Test Driven Development + +In this iteration, you are required to use TDD to create your classes. Use the interaction pattern to determine what a method should do and write one or more tests to verify that expected behavior. Then you can implement the method. You should always write code with the purpose of making a test pass. + +## Placing Pieces + +Update your program to request user input and allow them to place an individual piece. + +Your program should ask the user to enter a letter A-G. +Update the board to display the player's piece in the lowest available position of the selected column with an 'X'. + +The computer takes its turn by selecting one of the 7 columns at random. Update the board to display the computer's piece in the lowest available position of the selected column with an 'O'. + +The player and computer should be able to repeat this sequence and continue taking turns. + +### Invalid Column Selection + +Neither the player nor computer should be able to play in an invalid column. An invalid column is defined as one of the following: +1. Outside the range A-G +1. Full, i.e. there is no available position in the column + +If an invalid column is selected by the player, the program should display an error message and ask the player to select a valid column. The program should repeat this process until a valid column is selected. +* The one exception is when there are no valid columns available; i.e. the game board is full. In this case, the game is a draw, an endgame condition. + +If an invalid column is selected by the computer, the program should repeat until a valid column is selected. No error message should display to the user when the computer selects an invalid column. diff --git a/module1/projects/connect_four/iteration_3.md b/module1/projects/connect_four/iteration_3.md new file mode 100644 index 00000000..66b113d4 --- /dev/null +++ b/module1/projects/connect_four/iteration_3.md @@ -0,0 +1,77 @@ +--- +layout: page +title: Iteration 3 - Playing the Game +--- + +_[Back to Connect Four Home](./index)_ +_[Back to Requirements](./requirements)_ + +Now it's time to put together the components you've built in the last two iterations to make a working game. You are allowed to build any additional classes or methods you think may be useful to accomplish this. However, this project will be assessed on the spec outlined in the last two iterations, so don't remove any of the functionality from previously built classes. + +You are not expected to test anything related to user input and output in this iteration, but try to use TDD as much as possible to help you design your solution. + +You are not expected to follow the Game described below *exactly*. If you want to give your computer player more personality, feel free to do so. However, the information relayed to the user and received from the user should not change. For instance, when either the player or computer places a piece, you are not allowed to omit displaying the board to the user. For your convenience, at the end of this page you will find a checklist that summarizes all of the functionality you are expected to build. + +You are expected to build at least one additional class to complete this iteration. This can be a single class that is responsible for running the game. You should have very little code that is not contained in a class. + +## Main Menu + +When the user starts the game, they should see a welcome message that asks them if they want to play or quit. Whenever a game ends, they should return to this message so they can start a new game, or quit. + +``` +Welcome to CONNECT FOUR +Enter p to play. Enter q to quit. +``` + +## Setup + +Once the User has chosen to play, display a new game board and ask the player to place their first piece. + +### Placing Pieces + +The player starts the game by placing their first piece in a valid column. The computer then places their first piece in a randomly selected valid column. The player and computer should repeat this sequence and continue taking turns until an endgame condition is met. + +### End of Game + +The game ends when one of three endgame conditions is met: + +1. The player connects four of their pieces horizontally (in the same row), vertically (in the same column), or diagonally (in consecutively adjacent rows and columns). In this case, the player wins the game. +1. The computer connects four of their pieces horizontally, vertically, or diagonally. In this case, the computer wins the game. +1. The player can no longer place a piece. This occurs when there are no valid columns available; i.e. the game board is full. In this case, the game is a draw. + +When one of the end game conditions has been met, an appropriate message should be displayed. The player should be given the option to play again or quit via the Main Menu. + +## Functionality Checklist + +This checklist summarizes all of the functionality you are expected to build. This will be used to assess the completion of your project: + +**Welcome**: + +* A welcome message is displayed +* can be combined with Main Menu + +**Main Menu**: + +* User is shown the main menu where they can play or quit +* can be combined with Welcome + +**Setup**: + +* A new game board is displayed +* The player is asked to place their first piece. + +**Gameplay**: + +* The player places their first piece in a valid column. +* The computer places their first piece in a randomly selected valid column. +* The player and computer take turns placing a piece until an endgame condition is met. +* The game board is updated after each piece +* A player attempting to place a piece in an invalid column prompts user to enter a valid column, except in the case of a draw + +**End Game**: + +* The player connects four of their pieces horizontally, vertically, or diagonally. +* The computer connects four of their pieces horizontally, vertically, or diagonally. +* The player cannot select a valid column. +* The program reports the appropriate endgame status +* Game returns user back to the Main Menu diff --git a/module1/projects/connect_four/iteration_4.md b/module1/projects/connect_four/iteration_4.md new file mode 100644 index 00000000..344629c7 --- /dev/null +++ b/module1/projects/connect_four/iteration_4.md @@ -0,0 +1,41 @@ +--- +layout: page +title: Iteration 4 - Additional Features +--- + +_[Back to Connect Four Home](./index)_ | +_[Back to Requirements](./requirements)_ + +Add to your Connect Four game implementation with one or more of the following features: + +### HTTP + +* Make it so that a player can play over HTTP against a computer opponent. +* Use [this](http://backend.turing.edu/module1/projects/http_tutorial) tutorial as a starting place for creating your server. + +### Ruby Gem + +* Wrap the project in [Gem](https://en.wikipedia.org/wiki/RubyGems) using [Bundler](https://bundler.io/v1.16/guides/creating_gem.html) that can be run from the command line by typing `connect` anywhere on your machine rather than `ruby ./lib/connect_four.rb` from your project directory. + +### Intelligent Computer + +* Win: The computer always selects the column that would connect four of their pieces +* Block: The computer always selects the column to block the player with three connecting pieces +* When presented with Win vs. Block, the computer makes the decision to Win +* When presented with two or more different Block scenarios, selecting any Block is acceptable + +### Two Human Players + +* Give players the option of playing with two players. +* Each player enters a unique name. + +### Win/Loss Record Keeping + +* Track win/loss records for players based on a name that they enter that persists between plays (consider writing to CSV). +* Give players the option of seeing a list of the top ranked players based on their win percentage. + +### Time Keeping + +* Record the time it takes for a player to win a game. +* Track their fastest wins and fastest losses. +* Provide an option for users to view their personal statistics once they have entered their name. diff --git a/module1/projects/connect_four/overview.md b/module1/projects/connect_four/overview.md new file mode 100644 index 00000000..7797da16 --- /dev/null +++ b/module1/projects/connect_four/overview.md @@ -0,0 +1,73 @@ +--- +layout: page +title: Connect Four - Overview +--- + +_[Back to Connect Four Home](./index)_ + +## Project Requirements + +You are to build a playable game of Connect Four that runs in a REPL interface. The game will allow a single human player ("player") to play against a (simplistic) computer player ("computer"). The game will run from the command line with the following command: + +``` +$ ruby ./lib/connect_four.rb +``` + +From there, players will be asked to enter column names to place one of their pieces in a column. The computer will also place its own pieces. The player and the computer will continue to take turns until either one has won the game or they have played to a draw. + +Here is a representation of the start of a game. +``` +ABCDEFG +....... +....... +....... +....... +....... +....... +``` + +The Game is over when either the Player or Computer connects four of their pieces as described below, or the game ends in a draw (also described below). + +Here is a representation of the human player (the 'X' player) winning the game with four connected pieces horizontally (in the same row). +``` +ABCDEFG +....... +....... +...O... +...X... +..OXO.. +XXXXOO. +``` + +Here is a representation of the human player (the 'X' player) winning the game with four connected pieces vertically (in the same column). +``` +ABCDEFG +....... +....... +...X... +...X... +.OOX... +XOXXOO. +``` + +Here is a representation of the computer player (the 'O' player) winning the game with four connected pieces diagonally (in consecutively adjacent rows and columns). +``` +ABCDEFG +....... +....... +....OO. +...OXX. +..OXOX. +XOXXOOX +``` + +Here is a representation of a draw game. Neither the human player ('X') nor the computer player ('O') achieved four connected pieces horizontally, vertically, or diagonally. +``` +ABCDEFG +OXOXOOX +XOOXXOO +XXXOOXX +OXOXXOO +OOOXXOX +XXOXOOX +``` diff --git a/module1/projects/connect_four/peer_code_share.md b/module1/projects/connect_four/peer_code_share.md new file mode 100644 index 00000000..ed957954 --- /dev/null +++ b/module1/projects/connect_four/peer_code_share.md @@ -0,0 +1,23 @@ +--- +layout: page +title: Connect Four - Peer Code Share +--- + +_[Back to Connect Four Home](./index)_ + +## Peer Code Share + +You and your partner will team up with another pair to review each other's code and provide feedback. + +First, exchange Github repo links with the other team. + +Then, with your project partner, take 25 minutes to review the other team's code. You should write down answers to the following questions: + +1. Can you play the game? Is it easy to figure out how to play the game? Do you find any bugs as you play? +1. Discuss the code for the endgame conditions (`Player Wins`, `Computer Wins`, `Draw`). Is the logic easy to follow? Do the variable names make sense? Could this method be improved by creating additional helper methods? +* In the case that the other team did not write code for endgame conditions, discuss the code for the player and computer selecting a valid column. Answer the same questions above. +1. What classes and methods did the other team include that were not described in the project? How do these classes help organize the code? Are there additional classes or methods they could consider adding that might improve their code? +1. What other feedback do you have for the other team? +1. What other questions do you have for the other team? + +Once both teams have finished reviewing code, set up a 40 meeting with the other team. During that meeting, both teams should share their answers to the questions above. diff --git a/module1/projects/connect_four/requirements.md b/module1/projects/connect_four/requirements.md new file mode 100644 index 00000000..95854f73 --- /dev/null +++ b/module1/projects/connect_four/requirements.md @@ -0,0 +1,20 @@ +--- +layout: page +title: Connect Four - Requirements +--- + +_[Back to Connect Four Home](./index)_ + +The specifications give you ideas for some classes to help you start breaking this problem down, but you will also have to create some additional classes and methods to build an Object-Oriented solution to this problem. This means that there should be very little code outside of a class and you are using your classes to create objects that interact in some way. + +Additionally, this project will require you to use Test Driven Development for all methods that do not **rely** on user input. *Very few* methods should rely on user input. + +As a pair, you are both expected to commit frequently and use Pull Requests to merge your code with your partner's. Remember that there are many ways to contribute to a group effort - review the topics we discussed in your [Learning to Pair](https://docs.google.com/presentation/d/1SB65R2PkUBHoNHk3z5Q71D-ZVHPLdQ7wBagGjd6_AUU/edit?usp=sharing) lesson. + +Please read the [Rubric](./rubric) before getting started so that you know what is expected of you. + +* [Overview](./overview) +* [Iteration 1](./iteration_1) +* [Iteration 2](./iteration_2) +* [Iteration 3](./iteration_3) +* [Iteration 4](./iteration_4) diff --git a/module1/projects/connect_four/rubric.md b/module1/projects/connect_four/rubric.md new file mode 100644 index 00000000..bf471f66 --- /dev/null +++ b/module1/projects/connect_four/rubric.md @@ -0,0 +1,19 @@ +--- +layout: page +title: Connect Four - Evaluation Requirements +--- + +_[Back to Connect Four Home](./index)_ + + +Please reference [these instructions](./evaluation), to prepare for your project evaluation. + +## Evaluation Rubric + +
| **Exceeds Expectations** | **Meets Expectations** | **Approaching Expectations** | **Below Expectations** +-- | --- | --- | --- | --- +**Functionality** | 2 of the additional features in Iteration 4 are complete | All of the functionality in Iteration 3 is complete | Some of the functionality in Iteration 3 is not complete | Some of the functionality in Iterations 1 or 2 is not complete | +**Object Oriented Programming** | Project includes at least one additional class not outlined in the spec that does no command line input or output, adheres to SRP, and acts as a crucial piece of functionality in the program. | Project includes at least one additional class not outlined in the spec contained in its own file with no executable code outside the class. Very little code is not contained within a class. | Project includes at least one additional class not outlined in the spec. Code that is crucial to the setup, play, or end of a game may not be contained in a class. | Project does not include a class not outlined in the spec. The project does not use the required objects appropriately to accomplish the task. | +**Test Driven Development** | All methods throughout the project are fully unit and integration tested, including additional classes built in Iterations 3 or 4. No tests fail to accurately verify expected behavior. | No more than 2 tests fail to accurately verify expected behavior. All methods that do not rely on CLI are unit and integration tested. | Every method from iteration 1 or 2 does not include a test. More than 2 tests fail to accurately verify expected behavior. | Half the methods throughout the project are not tested or have tests that do not accurately verify expected behavior. | +**Version Control** | Project includes at least 10 pull requests that include helpful comments from both partners. | Project includes at least 10 pull requests and 30 commits. Insights show that one partner contributed no more than twice as much as the other in terms of lines of code or commits. Pull Requests were never merged by the author. | Project includes at least 5 pull requests and 20 commits. | Project has 5 or fewer pull requests or less than 20 commits. | +**Presentation and Professional Development** | All of the reflection questions are answered in the README, and all of the presentation topics are discussed. Students provide examples and ideas about how some things might be approaching differently on future projects in either/both the written and verbal presentations. | All of the reflection questions are answered in the README, and all of the presentation topics are discussed. | 1 reflection question or presentation topic is skipped or not answered thoughtfully. | More than 1 reflection question or presentation topic is skipped or not answered thoughtfully. | \ No newline at end of file diff --git a/module1/projects/connect_four/setup.md b/module1/projects/connect_four/setup.md new file mode 100644 index 00000000..93e9ce71 --- /dev/null +++ b/module1/projects/connect_four/setup.md @@ -0,0 +1,23 @@ +--- +layout: page +title: Connect Four - Setup +--- + +_[Back to Connect Four Home](./index)_ + +## Repository Setup + +Because this is a paired project, you will want to choose one person to create the project repository and invite the other person as a collaborator using the following steps: + +* Person A will create a git repository and link it to a GitHub repository. +* Person A will add Person B as a collaborator to the repository: + * From the GitHub Repository main page, click on `settings` + * In the left nav bar, click on `Collaborators` + * Search for a user and click `Add Collaborator` +* Person B will get an email invite to join the project as a collaborator. + * Click on the link in the email and accept the invitation. + * Clone the repository to your local machine. + +Once this setup is complete, both partners will be able to push to the GitHub repository, create Pull Requests and merge the Pull Requests. + +If you have more than one partner, Person A will add multiple collaborators as described above and each collaborator will receive an email to join the project. diff --git a/module1/projects/futbol/evaluation.md b/module1/projects/futbol/evaluation.md deleted file mode 100644 index 49f64136..00000000 --- a/module1/projects/futbol/evaluation.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -layout: page -title: Futbol Evaluation -length: 2 week -type: project ---- - -_[Back to Futbol Home](./index)_ - -For this project, you will submit your project with a robust README document for an asynchronous evaluation. - -Before you turn in the project, you and your group should be prepared to answer the questions in the checklist below. If you have any questions, please let your instructor know before the project submission deadline. - -## Evaluation readiness checklist: - -[ ] Demonstration of functional completeness - * Display to the viewer the ability to start the program via the runner file, and demonstrate a few of the statistics that can be calculated. - -[ ] Technical quality and organization of the code - * At a high level (not line by line), describe how you broke out this application. What classes did you create? What is the responsibility of each class? Why did you choose to design your code in this way? - * Is there a design decision that you made that you're particularly proud of? - * Did you use inheritence and/or modules in your project? Why did you choose to use one over the other? - * Were you able to implement a hash at some point in your project? If so, where? And why did you choose to use a hash instead of another data type? - -[ ] Identifying areas of code that you decided to refactor - * How did you identify areas of code to refactor? At a high level, how did you go about refactoring? - * Are there other areas of your code that you still wish to refactor? - -[ ] Discussion of collaboration/version control - * What was your collaboration like in this group project? How was it different working in a larger group compared to pairs? - * Were there any tools that you used to make collaboration easier? - -[ ] Discussion of test coverage - * Run your test suite and open the coverage report from SimpleCov. - * Show examples of unit and integration tests that you wrote. - * Run the Spec Harness. - * What was it like using the Spec Harness for this project? How did it inform your design or testing choices? - -Full instructions for submitting your group project can be found [here](https://gist.github.com/jamisonordway/a6fd8e8caaaf1b053dff302cbbaf9e0f). diff --git a/module1/projects/futbol/index.md b/module1/projects/futbol/index.md deleted file mode 100644 index 6ff0dc33..00000000 --- a/module1/projects/futbol/index.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -layout: page -title: Futbol ---- - -Let's build a system to do some analysis on futbol team performance. - -## Learning Goals - -* Build classes with single responsibilities. -* Write organized readable code. -* Use TDD as a design strategy. -* Design an Object Oriented Solution to a problem. -* Practice algorithmic thinking. -* Work in a group. -* Use Pull Requests to collaborate among multiple partners. - -## Project Description - -We will be using data from a fictional soccer league to analyze team performance for specific seasons and across seasons. We want to see who the best and worst performers are, as well as be able to pull statistics for individual teams. To that end we will create a `StatTracker` class that will provide us with the information we need. - -The first half of the project will focus on building the base statistics functionality through our `StatTracker`. As you build out this class, you will quickly realize that there is *waaaay* too much going on in one class; so, for the second half of the project we will switch our focus to reorganizing our code to practice good SRP! - -## Organization - -A key goal of this project is to write readable, organized, object-oriented code. Each of the methods we will implement should be defined as instance methods on `StatTracker`. However, all of the code for your project should not be contained in the `StatTracker` class. You should break your code into logical, organized components. - -We recommend taking a "red, green, refactor" approach. First, write tests, write code that makes the tests pass, and then focus on refactoring and organizing after you have working tests and code. It will be easier to make decisions about new classes, modules, methods, etc. when you have seen working code. - -We also encourage you to track your progress by utilizing a project management tool such as GitHub Projects or Trello; we will not be requiring a project management tool for the project, but it is a good habit to get into! - -See [the evaluation rubric](./rubric) for more details and what exactly you should accomplish in this project. - -## Testing - -Another key goal of this project is to utilize Test Driven Development. Because the data set is so large, it will be inefficient to use the actual dataset as your test data. Instead, you should make up your own test data. You can do this either by creating dummy CSV files, known as fixture files, or you can create dummy data within your test files. Either is a valid approach. - -A lesson available in Mod 1 is [Mocks and Stubs](../../lessons/mocks_stubs), which is another testing strategy that may come in handy during this project. We recommend starting with fixture files or dummy data in the test setup, and refactoring to using mocks and stubs if you feel comfortable with those tools. - -### Spec Harness - -In addition to your own tests, instructors will use [this Spec Harness](https://github.com/turingschool-examples/futbol_spec_harness) to assess the completion of your project. Prior to your evaluation, follow the direction in the README to set up the spec harness and verify that your code passes the tests. **NOTE: the spec harness is not a replacement for writing your own tests**. - -## Iterations - -We have separated the methods required for this project into sections below. - -* **Iteration 1:** [Setup and File I/O](./iterations/file_io) -* **Iteration 2:** [Statistics](./iterations/statistics) -* **Iteration 3:** [Re-Organization](./iterations/reorganization) -* **Iteration 4:** [Build a Website](./iterations/website) - -## Evaluation Rubric - -Your project will be assessed using [this rubric](./rubric). - -### Evaluation Preparation -Please reference [these instructions](./evaluation) to prepare for your live project evaluation. diff --git a/module1/projects/futbol/iterations/file_io.md b/module1/projects/futbol/iterations/file_io.md deleted file mode 100644 index 8dd693c1..00000000 --- a/module1/projects/futbol/iterations/file_io.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -layout: page -title: File I/O and Setup ---- - -_[Back to Futbol Home](../index)_ - -## Setup - -We have provided a starting repository for this project. That repository has the usual `lib` and `spec` directories that you have seen in the past, but also includes a `data` directory that includes three `.csv` files. These files are text files that include tables represented as comma-separated values (hence `.csv`). The first row includes headers, while every other row includes entries in the table. - -Begin by picking one team member to fork the project repository [here](https://github.com/turingschool-examples/futbol). -Once one of you has forked the repository, each of the other team members should clone that repository. - -In order to complete your setup: - -* One team member forks the repository [here](https://github.com/turingschool-examples/futbol) and adds the other(s) as collaborators. -* Each of the other team members accepts the invitation to collaborate and then clones the repository. -* Setup [SimpleCov](https://github.com/colszowka/simplecov) to monitor test coverage along the way. - -Note: we have linked the GitHub repository for SimpleCov, but you should not expect that those are the only resources you will use to set up these tools in your project. Use your research skills to find other resources to help you determine how to use these tools. You may want to consider using [Rubys CSV class](https://ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/CSV.html). - -## File I/O - -In order to get data into the system we're going to create, we're going to read information from CSV files. At this point, we don't expect that you have determined exactly what you will be doing with the information that you collect, so for now you may just want to print some information to the terminal about each record you read in. - -At a high level, if you create a runner file including the code below, you should drop into a pry session with an instance of `StatTracker` held in the `stat_tracker` variable. - -Note that `::from_csv` is a method you have defined called directly on the `StatTracker` class, and not an instance of `StatTracker`. - -`::from_csv` returns an instance of StatTracker. That instance of `StatTracker` will hold all of the information you need for the methods included in the remainder of the project description. - -```ruby -# runner.rb -require './lib/stat_tracker' - -game_path = './data/games.csv' -team_path = './data/teams.csv' -game_teams_path = './data/game_teams.csv' - -locations = { - games: game_path, - teams: team_path, - game_teams: game_teams_path -} - -stat_tracker = StatTracker.from_csv(locations) - -require 'pry'; binding.pry -``` diff --git a/module1/projects/futbol/rubric.md b/module1/projects/futbol/rubric.md deleted file mode 100644 index d30d4804..00000000 --- a/module1/projects/futbol/rubric.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: page -title: Futbol - Rubric ---- - -_[Back to Futbol Home](./index)_ - -## Evaluation Presentation -Please reference [these instructions](./evaluation) to prepare for your live evaluation. - - -## Rubric - -| Category | **Exceptional** | **Meets Expectations** | **Below Expectations** | **Well Below Expectations** | -| -------- | ------------------------------ | ------------------------- | ------------------------- | ------------------------------ | -| **Functionality** | Completes all 4 iterations | Completes all functionality in iterations 1 through 3; including the [refactoring deliverable](./iterations/reorganization) | Completes all functionality in iterations 1 and 2 | Completes only iteration 1| -| **Object Oriented Programming** | Students have implemented both inheritance and at least one module in a logical manner. Students can speak as to how/why inheritance and modules made sense for the given implementations, why they improve the organization of the code, and the distinction between the two. | Students have implemented either inheritance or at least one module in a logical manner. Students can speak as to how/why inheritance or modules made sense for the given implementation, and why it improves the organization of their code. No class is over 150 lines long. | Students can clearly identify the responsibility of each class that they created and the methods that they wrote. Students are able to describe why they have organized their code in the way they did. No class is over 200 lines long. | Students have difficulty explaining the reason they have organized their code in the way that they did. They may have few files that seem to be doing the vast majority of the work in the project, and have not drawn clear lines between the responsibilities of different classes they have created. | -| **Ruby Conventions and Mechanics** | Classes, methods, and variables are well named so that they clearly communicate their purpose. Code is all properly indented and syntax is consistent. No methods are longer than 10 lines long. Most enumerables/data structures chosen are the most efficient tool for a given job, and students can speak as to why those enumerables/data structures were chosen. | Code is mostly properly indented, spaced, and lines are not excessively long. Class, method, variable, and file names follow convention. Some enumerables/data structures chosen are the most efficient tool for a given job, and students can speak as to why those enumerables/data structures were chosen. At least one hash is implemented in a way that makes logical sense. | Code demonstrates some proper indenting and spacing. Class, method, variable, and file names inconsistently follow convention. Few enumerables/data structures chosen are the most efficient tool for a given job. Students may not be able to speak as to why those enumerables/data structures were chosen. No hashes are implemented, or are implemented in an inappropriate use case. | Code is not properly indented and spaced and lines are excessively long. Class, method, variable, and file names do not follow convention | -| **Test Driven Development** | Mocks and/or stubs are used appropriately to ensure one of the following: testing is more robust (i.e., testing methods that might not otherwise be tested due to factors like randomness or user input), testing is more efficient (i.e., not reading a full CSV file every time you call a method for a test), or that classes can be tested without relying on functionality from other classes. Students are able to speak as to how mocks and/or stubs are fulfilling the above conditions. Spec harness runs in 5 seconds or less. | Test coverage is above 95%. Students can indentify unit and integration testing. | Test coverage is above 90%. Students may not be able to identify unit or integration tests. Git history may demonstrate that students are writing implementation code and then writing tests. | Test coverage is below 90%. | - -**Required:** Students will document and implement a code review process throughout the project whereby comments on pull requests are addressed before PRs are merged. Students contributed roughly equally to the project in terms of number of commits and lines of code. Commits are made in small chunks of functionality. Students used pull requests as a collaboration tool by reviewing each other’s PRs, making comments, and never merging their own PRs. - -Remember that there are many ways to contribute to a group effort - review the topics we discussed in your [Learning to Pair](https://docs.google.com/presentation/d/1SB65R2PkUBHoNHk3z5Q71D-ZVHPLdQ7wBagGjd6_AUU/edit?usp=sharing) lesson. diff --git a/module1/projects/futbol_pd/evaluation.md b/module1/projects/futbol_pd/evaluation.md new file mode 100644 index 00000000..a0e66eec --- /dev/null +++ b/module1/projects/futbol_pd/evaluation.md @@ -0,0 +1,34 @@ +--- +layout: page +title: Futbol Evaluation +length: 1 week +type: project +--- + +_[Back to Futbol Home](./index)_ + +For this project, you will have a live evaluation over Zoom with an instructor. You and your group are expected to prepare a presentation to speak to each of the top-level topics listed below. Every member of the group is expected to speak during the presentation. Each top-level topic (has a check box) should be discussed. The bullet points below each topic are provided for ideas and guidance as things you can talk about. You do NOT need to address every single bullet point, just every topic. If you have any questions, please let your instructor know before the project submission deadline. + + +## Presentation Topics: + +[ ] Discuss Project Management process + * What tool(s) did you use for managing tasks and assignments + * What worked well and not so well about this process? + * Did anything about this process change mid-project? If so, how did that change come about? For example, how was this issue approached and a change decided upon by the group? + +[ ] Review Git Workflow + * Show an example of a PR with lots of team collaboration and discussion + * Did you have any rules or guidelines in place to ensure effective workflow? + * What was challenging about working with 3-5 people on one repository? + +[ ] Collaboration & Communication + * Describe how feedback was shared amongst team members. + * Did the team ever meet with the intention of solving a non-technical problem? For example, to discuss a change to a process. Were these meetings ad hoc or regularly scheduled? If you could do it over again, would you have changed how you approached non-technical communication with your team? + * Were there any pieces of the DTR that needed to be re-visited mid-project due to something not working out as expected? + * Give a summary of your Retro. What formats did the group consider? Why did you choose the format you did? Did this retro feel effective? What might you try differently the next time you run a group retro? Summarize the outcome of the retro. + +[ ] Technical Review - **All of the list items below are required**, however each talking point can be brief. + * Run the test suite and show the coverage report + * Demonstrate the functionality of the project (show how it works). You can use a runner file to demonstrate a few of the statistics that can be calculated. + * Technical design: At a high level (not line by line), describe how you broke out this application, and describe why you chose to design your code in this way. diff --git a/module1/projects/futbol_pd/index.md b/module1/projects/futbol_pd/index.md new file mode 100644 index 00000000..1675432b --- /dev/null +++ b/module1/projects/futbol_pd/index.md @@ -0,0 +1,62 @@ +--- +layout: page +title: Futbol - PD +--- + +Let's build a system to do some analysis on futbol team performance. +And let's also build a system to do some analysis on YOUR team performance, too! + +## Learning Goals + +* Building software in teams + * Use Pull Requests to collaborate among multiple partners + * Practice giving and receiving feedback with teammates + * Establish a project organization process +* Design an Object Oriented Solution to a problem with multiple people +* Use TDD and write clean Ruby following SRP and DRY principles + +## Project Description + +We will be using data from a fictional soccer league to analyze team performance for specific seasons and across seasons. We want to see who the best and worst performers are, as well as be able to pull statistics for individual teams. To that end we will create a `StatTracker` class that will provide us with the information we need. + +The first step of the project will focus on establishing norms for your group. This should include the following: project organization process, git workflow expectations, and DTR *at a minimum*. + +Next, you will plan and design your solution with your group. This probably doesn't actually involve writing any code yet. Remember, the primary purpose of this project is to practice building software in a team setting. You need a good design and plan before folks can break off and do their own thing. + +Finally, once you have strong processes and a plan in place, the project can begin focusing on building the base statistics functionality through our `StatTracker`. + +## Code Organization + +Each of the methods we will implement should be defined as instance methods on `StatTracker`. However, all of the code for your project should not be contained in the `StatTracker` class. You should break your code into logical, organized components. + +We recommend taking a "red, green, refactor" approach. First, write tests, write code that makes the tests pass, and then focus on refactoring and organizing after you have working tests and code. It will be easier to make decisions about new classes, modules, methods, etc. when you have seen working code. + +A key goal of this project is to work effectively in teams of 3-5 people. We **STRONGLY** encourage you to track your progress by utilizing a project management tool such as GitHub Projects or Trello; we will not be requiring a project management tool for the project, but it is a good habit to get into! If you choose not to use a project management tool, your group should still decide how tasks are being assigned to group members and how the status of those tasks should be communicated to the group. + +See [the evaluation rubric](./rubric) for more details and what exactly you should accomplish in this project. + +## Testing + +As with all projects, you should utilize Test Driven Development. Because the data set is so large, it will be inefficient to use the actual dataset as your test data. Instead, you should consider making up your own test data. You can do this either by creating dummy CSV files, known as fixture files, or you can create dummy data within your test files. Either is a valid approach. + +A lesson available in Mod 1 is [Mocks and Stubs](../../lessons/mocks_stubs), which is another testing strategy that may come in handy during this project. We recommend starting with fixture files or dummy data in the test setup, and refactoring to using mocks and stubs if you feel comfortable with those tools. + +### Spec Harness + +In addition to your own tests, you can use [this Spec Harness](https://github.com/turingschool-examples/futbol_spec_harness) to assess the accuracy of your project calculations. The spec harness contains a small number of tests to verify that the methods you wrote work as intended according to the project technical requirements. **NOTE: the spec harness is not a replacement for writing your own tests**. + +## Iterations + +We have separated the methods required for this project into sections below. + +* **Iteration 1:** [Group Norms and Project Design](./iterations/group_norms) +* **Iteration 2:** [Setup, File I/O, and Statistics](./iterations/file_io_stats) +* **Iteration 3:** [Retro](./iterations/retro) +* **Iteration 4:** [Process Change](./iterations/team_statistics) + +## Evaluation Rubric + +Your project will be assessed using [this rubric](./rubric). + +### Evaluation Presentation +Please reference [these instructions](./evaluation) to prepare for your live project evaluation. diff --git a/module1/projects/futbol/iterations/command_line.md b/module1/projects/futbol_pd/iterations/command_line.md similarity index 100% rename from module1/projects/futbol/iterations/command_line.md rename to module1/projects/futbol_pd/iterations/command_line.md diff --git a/module1/projects/futbol_pd/iterations/file_io_stats.md b/module1/projects/futbol_pd/iterations/file_io_stats.md new file mode 100644 index 00000000..0a928c5e --- /dev/null +++ b/module1/projects/futbol_pd/iterations/file_io_stats.md @@ -0,0 +1,93 @@ +--- +layout: page +title: Setup, File I/O, and Statistics +--- + +_[Back to Futbol Home](../index)_ + +## Setup + +We have provided a starting repository for this project. That repository has the usual `lib` and `spec` directories that you have seen in the past, but also includes a `data` directory that includes three `.csv` files. These files are text files that include tables represented as comma-separated values (hence `.csv`). The first row includes headers, while every other row includes entries in the table. + +Begin by picking one team member to fork the project repository [here](https://github.com/turingschool-examples/futbol). +Once one of you has forked the repository, each of the other team members should clone that repository. + +In order to complete your setup: + +* One team member forks the repository [here](https://github.com/turingschool-examples/futbol) and adds the other(s) as collaborators. +* Each of the other team members accepts the invitation to collaborate and then clones the repository. +* Setup [SimpleCov](https://github.com/colszowka/simplecov) to monitor test coverage along the way. + +Note: we have linked the GitHub repository for SimpleCov, but you should not expect that those are the only resources you will use to set up these tools in your project. Use your research skills to find other resources to help you determine how to use these tools. You may want to consider using [Rubys CSV class](https://ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/CSV.html). + +## File I/O + +In order to get data into the system we're going to create, we're going to read information from CSV files. At this point, we don't expect that you have determined exactly what you will be doing with the information that you collect, so for now you may just want to print some information to the terminal about each record you read in. + +At a high level, if you create a runner file including the code below, you should drop into a pry session with an instance of `StatTracker` held in the `stat_tracker` variable. + +Note that `::from_csv` is a method you have defined called directly on the `StatTracker` class, and not an instance of `StatTracker`. + +`::from_csv` returns an instance of StatTracker. That instance of `StatTracker` will hold all of the information you need for the methods included in the remainder of the project description. + +```ruby +# runner.rb +require './lib/stat_tracker' + +game_path = './data/games.csv' +team_path = './data/teams.csv' +game_teams_path = './data/game_teams.csv' + +locations = { + games: game_path, + teams: team_path, + game_teams: game_teams_path +} + +stat_tracker = StatTracker.from_csv(locations) + +require 'pry'; binding.pry +``` + +## Statistics + +Each of the methods described below should be implemented as instance methods on `StatTracker` in order for the spec harness to work properly. + +### Game Statistics + +| Method | Description | Return Value | +| ------ | ----------- | ------------ | +|`highest_total_score`| Highest sum of the winning and losing teams' scores | Integer | +|`lowest_total_score`| Lowest sum of the winning and losing teams' scores | Integer | +|`percentage_home_wins`| Percentage of games that a home team has won (rounded to the nearest 100th) | Float | +|`percentage_visitor_wins`| Percentage of games that a visitor has won (rounded to the nearest 100th) | Float | +|`percentage_ties`| Percentage of games that has resulted in a tie (rounded to the nearest 100th) | Float | +|`count_of_games_by_season`| A hash with season names (e.g. 20122013) as keys and counts of games as values | Hash | +|`average_goals_per_game`| Average number of goals scored in a game across all seasons including both home and away goals (rounded to the nearest 100th)| Float | +|`average_goals_by_season`| Average number of goals scored in a game organized in a hash with season names (e.g. 20122013) as keys and a float representing the average number of goals in a game for that season as values (rounded to the nearest 100th)| Hash | + + +### League Statistics + +| Method | Description | Return Value | +| ------ | ----------- | ------------ | +|`count_of_teams`| Total number of teams in the data. | Integer | +| `best_offense` | Name of the team with the highest average number of goals scored per game across all seasons. | String | +| `worst_offense` | Name of the team with the lowest average number of goals scored per game across all seasons. | String | +| `highest_scoring_visitor` | Name of the team with the highest average score per game across all seasons when they are away. | String | +| `highest_scoring_home_team` | Name of the team with the highest average score per game across all seasons when they are home. | String | +| `lowest_scoring_visitor` | Name of the team with the lowest average score per game across all seasons when they are a visitor. | String | +| `lowest_scoring_home_team` | Name of the team with the lowest average score per game across all seasons when they are at home. | String | + +### Season Statistics + +These methods each take a season id as an argument and return the values described below. + +| Method | Description | Return Value | +| ------ | ----------- | ------------ | +| `winningest_coach` | Name of the Coach with the best win percentage for the season | String | +| `worst_coach` | Name of the Coach with the worst win percentage for the season | String | +| `most_accurate_team` | Name of the Team with the best ratio of shots to goals for the season | String | +| `least_accurate_team` | Name of the Team with the worst ratio of shots to goals for the season | String | +| `most_tackles` | Name of the Team with the most tackles in the season | String | +| `fewest_tackles` | Name of the Team with the fewest tackles in the season | String | diff --git a/module1/projects/futbol/iterations/game_statistics.md b/module1/projects/futbol_pd/iterations/game_statistics.md similarity index 100% rename from module1/projects/futbol/iterations/game_statistics.md rename to module1/projects/futbol_pd/iterations/game_statistics.md diff --git a/module1/projects/futbol_pd/iterations/group_norms.md b/module1/projects/futbol_pd/iterations/group_norms.md new file mode 100644 index 00000000..32df4b63 --- /dev/null +++ b/module1/projects/futbol_pd/iterations/group_norms.md @@ -0,0 +1,48 @@ +--- +layout: page +title: Establishing Group Norms and Project Design +--- + +_[Back to Futbol Home](../index)_ + +## Group Norms +Your group should plan and expect to spend _at least_ the first full project day on iteration 1. We've provided some resources to guide this iteration, however you are encouraged to explore on your own and come up with a plan that works best for your team. + +### Git Workflow Expectations +You've already spent a lot of time this mod working with [git](https://backend.turing.edu/module1/lessons/git_and_github) and [git workflow](https://frontend.turing.edu/lessons/module-1/git-collaboration.html). Now, you will be collaborating with three or more people for the first time. Spend some time with your group reviewing git workflow and determine the [workflow](https://backend.turing.edu/module1/lessons/git_for_pairs) that will be best for your group. While you have flexibility as to what this means for you, it should include the use of branches and pull requests for merging changes. We never want to merge directly to main. + + +### Communication and Collaboration +We have a lot of tools for facilitation good communication and collaboration in our group. Many of these tools you will use on the job as well: Slack, Github, [giving and receiving feedback](https://docs.google.com/presentation/d/1nphMrfO_8TYzZ5hbP4w5Fp0zQzKDf4JFwMB4om9pt4M/edit?usp=sharing), [pairing techniques](https://docs.google.com/presentation/d/16kBalLWirvCLzoZriOaldxUgLlDqrFahbD9RJS0AlX8/edit?usp=sharing), and performing a [DTR](https://docs.google.com/document/d/1HFWSZExSWgGJdqLkEH4DXs-z1gZxMNkv4n1NO9U1eJU/copy) before beginning work with a new team. Set expectations with your team about how and how often communication should be happening. Remember, communication doesn't just mean live (or on Zoom). Communication can be asynchronous when we do a code review or leave messages in Slack that don't require an immediate response. Good communication can mean letting your team know you'll miss the morning check-in because you have a doctor's appointment, or apologizing if you forgot a meeting and detailing your plan for getting caught up. + +## Project Organization, Planning, and Design + +This topic will probably be the one with the most unknowns for the group. We've provided a lot of resources on code focused workflows and communication, but we haven't talked much about how to organize projects. This is up to you! + +Your group should research different methodologies and tools for project organization. You might choose to use an issue tracker like [Trello](https://trello.com/en) or [Github Projects](https://docs.github.com/en/issues/planning-and-tracking-with-projects). You might decide to use things like calendar events to plan meetings and check-ins. It's also important to not overdo it. There are so many ways to organize projects. You don't need to do EVERYTHING. Pick one or two things to try out and see how it goes. The expectation is not that you run a perfect project, but that you start practicing with some of the tools and get a feel for what works well when building software with a team. + +### Code Design + +There are a few things to consider when deciding how you want to organization your code: + +* What classes do you need? + * Classes should be compact. + * Classes should have a single responsibility - you should be able to describe what a class is responsible for in one sentence. +* Use the tools we have learned recently when thinking about reorganization - [Modules](https://backend.turing.edu/module1/lessons/modules), [Inheritance](https://backend.turing.edu/module1/lessons/inheritance), [Class Methods](https://backend.turing.edu/module1/lessons/class_methods), and Plain Old Ruby Objects (POROs). +* What makes the most sense for how to break this out in to pieces that individuals or pairs can work on. Odds are, you won't be mob programming the entire project. +* How will you determine when something is "good enough" to move on to the next thing (potential to refactor later)? + +## Deliverables +Your iteration deliverable is to [create a README](https://backend.turing.edu/module1/lessons/writing_a_readme) with the following. As you craft your answers, consider how you might talk about these same topics in a job interview after you graduate. + +* A 1-2 summary or bullet points outlining your plan for check-ins throughout the duration of the project. + +* A 2-4 sentence summary of your plan for project organization and workflow. This can include bullet points. If you plan to use a project management tool, please include a link to your project board. + +* A 2-3 sentence summary describing the different approaches your group discussed for project organization and how you collectively made a decision on which to use. + +* A 2-3 sentence summary describing your approach to the code design. + +* Include link to your initial DTR document and the date it was completed. If you do additional DTRs later in the project, you should link the revised versions here as well with the date. New versions should be listed alongside older versions. Do not delete old DTRs. + +* Create a section in your README called "Contributors". List each group member's name and link to their LinkedIn and Github profiles. diff --git a/module1/projects/futbol/iterations/league_statistics.md b/module1/projects/futbol_pd/iterations/league_statistics.md similarity index 100% rename from module1/projects/futbol/iterations/league_statistics.md rename to module1/projects/futbol_pd/iterations/league_statistics.md diff --git a/module1/projects/futbol/iterations/reorganization.md b/module1/projects/futbol_pd/iterations/reorganization.md similarity index 100% rename from module1/projects/futbol/iterations/reorganization.md rename to module1/projects/futbol_pd/iterations/reorganization.md diff --git a/module1/projects/futbol_pd/iterations/retro.md b/module1/projects/futbol_pd/iterations/retro.md new file mode 100644 index 00000000..23eaa490 --- /dev/null +++ b/module1/projects/futbol_pd/iterations/retro.md @@ -0,0 +1,33 @@ +--- +layout: page +title: Retrospective +--- + +_[Back to Futbol Home](../index)_ + +## Retrospective + +The group should perform a retrospective (often just called "retro"). There are many ways to do a project retro and lots of tools we can use to facilitate them. A quick Google search will yield dozens of links to resources about how, why, when, etc. as well as tools you can use to facilitate a retro. + +Here are some links to get you started: +* [Retrospectives by Atlassian](https://www.atlassian.com/team-playbook/plays/retrospective) +* [How to run an effective project retrospective meeting](https://www.smarttask.io/blog/project-retrospective-meeting) +* [ How to run a retrospective by Mural](https://www.mural.co/blog/sprint-retrospective) + +For this iteration, research how to run a retro. Collectively decide on a method and then do it! + +You should plan to discuss a summary of your retro during your project presentation. Here are some ideas of ways you can talk about it during the eval: +* What formats did the group consider? +* Why did you choose the format you did? +* Did this retro feel effective? What might you try differently the next time you run a group retro? +* Summarize the outcome of the retro. + + +## Deliverables +In addition to giving a summary of your retro during the evaluation, AFTER you do your retro, add to your README: + +* The name of and links (if applicable) to any tools you used for retro +* Top 3 things that went well during your project +* Top 3 things your team would do differently next time + +If you used a format for your retro that didn't include what went well and what you would change, you can adjust bullet points 2 and 3 accordingly. diff --git a/module1/projects/futbol/iterations/season_statistics.md b/module1/projects/futbol_pd/iterations/season_statistics.md similarity index 100% rename from module1/projects/futbol/iterations/season_statistics.md rename to module1/projects/futbol_pd/iterations/season_statistics.md diff --git a/module1/projects/futbol/iterations/statistics.md b/module1/projects/futbol_pd/iterations/statistics.md similarity index 94% rename from module1/projects/futbol/iterations/statistics.md rename to module1/projects/futbol_pd/iterations/statistics.md index d77f7da8..a427280d 100644 --- a/module1/projects/futbol/iterations/statistics.md +++ b/module1/projects/futbol_pd/iterations/statistics.md @@ -5,9 +5,7 @@ title: Statistics _[Back to Futbol Home](../index)_ -**These Statistics should be done the Monday before the project is due!** - -Each of the methods described below should be implemented as instance methods on `StatTracker`. +Each of the methods described below should be implemented as instance methods on `StatTracker` in order for the spec harness to work properly. ### Game Statistics @@ -60,6 +58,6 @@ Each of the methods below take a team id as an argument. Using that team id, you | `worst_season` | Season with the lowest win percentage for a team. | String | | `average_win_percentage` | Average win percentage of all games for a team. | Float | | `most_goals_scored` | Highest number of goals a particular team has scored in a single game. | Integer | -| `fewest_goals_scored` | Lowest numer of goals a particular team has scored in a single game. | Integer | +| `fewest_goals_scored` | Lowest number of goals a particular team has scored in a single game. | Integer | | `favorite_opponent` | Name of the opponent that has the lowest win percentage against the given team. | String | | `rival` | Name of the opponent that has the highest win percentage against the given team. | String | diff --git a/module1/projects/futbol/iterations/team_statistics.md b/module1/projects/futbol_pd/iterations/team_statistics.md similarity index 77% rename from module1/projects/futbol/iterations/team_statistics.md rename to module1/projects/futbol_pd/iterations/team_statistics.md index 7bb0d5f6..61a44b83 100644 --- a/module1/projects/futbol/iterations/team_statistics.md +++ b/module1/projects/futbol_pd/iterations/team_statistics.md @@ -1,10 +1,14 @@ --- layout: page -title: Team Statistics +title: Process Change --- _[Back to Futbol Home](../index)_ +Now that you've completed your first retro, make some changes to your group's process that resulted from retro, and continue working on some more statistics. Document these changes in your README. Consider how the changes are working. Keep some notes for a future retro of what's going well and what isn't going so well this second time around. + +## Team Statistics + Each of the methods below take a team id as an argument. Using that team id, your instance of StatTracker will provide statistics for a specific team. | Method | Description | Return Value | @@ -14,7 +18,7 @@ Each of the methods below take a team id as an argument. Using that team id, you | `worst_season` | Season with the lowest win percentage for a team. | String | | `average_win_percentage` | Average win percentage of all games for a team. | Float | | `most_goals_scored` | Highest number of goals a particular team has scored in a single game. | Integer | -| `fewest_goals_scored` | Lowest numer of goals a particular team has scored in a single game. | Integer | +| `fewest_goals_scored` | Lowest number of goals a particular team has scored in a single game. | Integer | | `favorite_opponent` | Name of the opponent that has the lowest win percentage against the given team. | String | | `rival` | Name of the opponent that has the highest win percentage against the given team. | String | | `biggest_team_blowout` | Biggest difference between team goals and opponent goals for a win for the given team. | Integer | diff --git a/module1/projects/futbol/iterations/website.md b/module1/projects/futbol_pd/iterations/website.md similarity index 100% rename from module1/projects/futbol/iterations/website.md rename to module1/projects/futbol_pd/iterations/website.md diff --git a/module1/projects/futbol/kick_off/index.md b/module1/projects/futbol_pd/kick_off/index.md similarity index 100% rename from module1/projects/futbol/kick_off/index.md rename to module1/projects/futbol_pd/kick_off/index.md diff --git a/module1/projects/futbol_pd/rubric.md b/module1/projects/futbol_pd/rubric.md new file mode 100644 index 00000000..c440682d --- /dev/null +++ b/module1/projects/futbol_pd/rubric.md @@ -0,0 +1,23 @@ +--- +layout: page +title: Futbol - Rubric +--- + +_[Back to Futbol Home](./index)_ + +## Evaluation Presentation +Please reference [these instructions](./evaluation) to prepare for your live evaluation. + + +## Rubric + +| Category | **Meets Expectations** | **Approaching Expectations** | **Below Expectations** | +| -------- | ---------------------- | ---------------------- | --------------------------- | +| **Presentation** | All [list items](./evaluation) are covered in the project presentation. Every group member actively participates during the evaluation. | 3/4 of presentation topics are discussed (can update with actual number when list is updated). Some group members do not actively participate in the evaluation. | 2/4 or fewer presentation topics are discussed.| +| **Project Organization** | Students document and implement a project organization process throughout the project whereby tasks are broken out and assigned in advance of being worked on. | Students document a project organization process but do not always follow the process by assigning tasks in advance or updating the status of tasks to the team in a timely manner. | Students do not implement any sort of project organization workflow. | +| **Git Workflow** | Students document and implement a code review process throughout the project whereby comments on pull requests are addressed before PRs are merged. Students used pull requests as a collaboration tool by reviewing each other’s PRs, making comments, and never merging their own PRs. Students contributed roughly equally to the project in terms of number of commits and lines of code. Commits are made in small chunks of functionality. | Students use branches and PRs but comment infrequently, or comments are of little substance (ex: “nice job!”). | Git workflow is not used. On multiple occasions, code is pushed directly to main. Students merge their own PRs. There is more than 50% discrepancy of lines of code committed between the highest and lowest code contributor. | +| **Collaboration & Communication** | The group: 1) Regularly provides actionable feedback to others in the group(verbal or written), 2) Has regular check-ins, 3) Completes a DTR at least once throughout the duration of the project. | The group does 2/3 of the actions described for “Meets Expectations” | The group does 1 or 0 of the actions described for “Meets Expectations” | +| **Code & Testing** | Code follows ruby convention, SRP, and DRY principles probably includes the use of things like modules and inheritance. Test coverage is above 95%. Students can identify unit and integration testing. | Code follows ruby convention, SRP, and DRY principles but may have some gaps in execution. Test coverage is above 90%. | Code does not follow ruby convention, SRP and DRY principles. Test coverage is below 90%. | + + +Remember that there are many ways to contribute to a group effort - review the topics we discussed in your [Learning to Pair](https://docs.google.com/presentation/d/1SB65R2PkUBHoNHk3z5Q71D-ZVHPLdQ7wBagGjd6_AUU/edit?usp=sharing) lesson. From aef329257adfc391bc5ed0b09cee8895672a157c Mon Sep 17 00:00:00 2001 From: Juliet Eyraud Date: Tue, 14 May 2024 18:17:55 -0500 Subject: [PATCH 3/4] uncomment projects --- module1/projects/index.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/module1/projects/index.md b/module1/projects/index.md index 0e853bd1..6c2837fb 100644 --- a/module1/projects/index.md +++ b/module1/projects/index.md @@ -6,10 +6,12 @@ title: Module 1 - Projects ## Required Projects The following projects will be assigned and their completion is required to be promoted to module 2. - - - - - - + +- Week 1 (Ungraded): [Credit Check](./credit_check.markdown) + +- Week 1-2 (Solo): [Flash Cards](./flashcards/) +- Week 2-3 (Solo): [DMV](./dmv/) + +- Week 3-4 (Paired): [Battleship](./battleship/) +- Week 5-6 (Group Final): [Futbol](./futbol_pd/) From 42d5b1f4b001c9fc40e044a795afb5669f23e8d7 Mon Sep 17 00:00:00 2001 From: Juliet Eyraud Date: Fri, 17 May 2024 16:21:17 -0500 Subject: [PATCH 4/4] Add JS extension to DMV project --- module1/projects/dmv/iteration_4.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/module1/projects/dmv/iteration_4.md b/module1/projects/dmv/iteration_4.md index 8ac72abe..4c39b260 100644 --- a/module1/projects/dmv/iteration_4.md +++ b/module1/projects/dmv/iteration_4.md @@ -9,11 +9,14 @@ _[Back to Requirements](./requirements)_ ## Extensions ### Option 1 +Use [this repository](https://github.com/turingschool-examples/the_dmv_extension_js) to practice making these DMV objects using JavaScript instead of Ruby! Follow instructions in the README to make the `registrant_test.js` file tests pass. + +### Option 2 Find your own data set to work with and do something interesting with it. If you choose this option, check in with an instructor before starting. * Here's a good place to start your data hunt: [Data.gov](https://catalog.data.gov/dataset) -### Option 2 +### Option 3 Calculate some analytics about your existing data sets: * EV Registrations: * Find the most popular make/model registered