diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 4c901c8..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -# Change Log -All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). - -## [Unreleased] -### Changed -- Add a new arity to `make-widget-async` to provide a different widget shape. - -## [0.1.1] - 2018-02-13 -### Changed -- Documentation on how to make the widgets. - -### Removed -- `make-widget-sync` - we're all async, all the time. - -### Fixed -- Fixed widget maker to keep working when daylight savings switches over. - -## 0.1.0 - 2018-02-13 -### Added -- Files from the new template. -- Widget maker public API - `make-widget-sync`. - -[Unreleased]: https://github.com/your-name/card-game/compare/0.1.1...HEAD -[0.1.1]: https://github.com/your-name/card-game/compare/0.1.0...0.1.1 diff --git a/README.md b/README.md deleted file mode 100644 index c7c2e28..0000000 --- a/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# card-game - -An iteratively designed card game. - -## Installation - -Install [Docker](https://store.docker.com/search?type=edition&offering=community). - -`git clone https://github.com/kenan-rhoton/card-game` - -## Usage - -`docker-compose build && docker-compose up` - -## Development - -While working on backend stuff (Clojure), please keep a terminal open at *all* times with the following command running: - -`docker-compose run backend lein test-refresh` - -While working on frontend stuff (Javascript), please keep a terminal open at *all* times with the following command running: - -`docker-compose run frontend yarn test-refresh` - -This will give you instant feedback through the tests. - -If you don't want to use docker (and have Leiningen/Yarn installed), you can use the non-docker versions of the commands, which **must** be executed from within the respective directories (`backend`and `frontend` respectively): - -`lein test-refresh` -`yarn test-refresh` - -For End-to-End testing, use [testcafe](http://devexpress.github.io/testcafe/documentation/test-api/) to run the e2e tests: - -`docker-compose -f docker-compose.yml -f docker-compose.e2e.yml run e2e test` - -To run *all* tests, use: - -`bash fulltest.sh` - -## License - -Copyright © 2018 Kenan Rhoton - -Distributed under the MIT License. diff --git a/backend/old_tests/api/base_test.clj b/backend/old_tests/api/base_test.clj deleted file mode 100644 index d6b812c..0000000 --- a/backend/old_tests/api/base_test.clj +++ /dev/null @@ -1,48 +0,0 @@ -(ns api.base-test - (:require [expectations.clojure.test :refer :all] - [clojure.test :as ctest] - [mocking :as mocking] - [api.base :as api] - [configs.messages :as messages])) - -(ctest/use-fixtures :each mocking/mock-persistence) - -(defexpect create-game - - (let [game (api/create-game)] - ; Checking it has been created - (expect - #(contains? % :game-id) - game) - - (expect - #(contains? % :player-id) - game) - - (expect - #(= 5 (count (:rows %))) - game))) - -(defexpect add-player - (let [game (api/create-game) - opponent (api/add-player (:game-id game))] - (expect - #(contains? % :player-id) - opponent) - - (expect - #(not (contains? % :error)) - opponent) - - (expect - true - (= (:game-id game) (:game-id opponent))) - - ; A third player causes an error - (expect - {:error messages/too-many-players} - (api/add-player (:game-id game))) - - (expect - false - (= (:player-id game) (:player-id opponent))))) diff --git a/backend/old_tests/api/newgame_test.clj b/backend/old_tests/api/newgame_test.clj deleted file mode 100644 index c3bb6b8..0000000 --- a/backend/old_tests/api/newgame_test.clj +++ /dev/null @@ -1,48 +0,0 @@ -(ns api.newgame-test - (:require [expectations.clojure.test :refer :all] - [clojure.test :as ctest] - [mocking :as mocking] - [api.base :as api] - [configs.hands :as hands] - [configs.messages :as messages])) - -(ctest/use-fixtures :each mocking/mock-persistence) - -(defexpect sanity-check - (let [game (api/create-game)] - (expect - #(contains? % :game-id) - game) - (expect - #(contains? % :player-id) - game) - (expect - #(= (count (:hand %)) (count hands/default-hand)) - game) - (expect - #(= 5 (count (:rows %))) - game))) - -(defexpect joining-a-game - (let [game (api/create-game) - opponent (api/add-player (:game-id game))] - (expect - #(contains? % :player-id) - opponent) - - (expect - #(not (contains? % :error)) - opponent) - - (expect - true - (= (:game-id game) (:game-id opponent))) - - ; A third player causes an error - (expect - {:error messages/too-many-players} - (api/add-player (:game-id game))) - - (expect - false - (= (:player-id game) (:player-id opponent))))) diff --git a/backend/old_tests/mocking.clj b/backend/old_tests/mocking.clj deleted file mode 100644 index 92a9c28..0000000 --- a/backend/old_tests/mocking.clj +++ /dev/null @@ -1,15 +0,0 @@ -(ns mocking - (:require [persistence.persistence :as persistence])) - -(def mock-game (atom nil)) - -(defn mock-persistence - [tests] - (with-redefs - [persistence/next-id (constantly 0) - persistence/save-game (fn [a] - (reset! mock-game a)) - persistence/fetch-game (fn [x] - @mock-game)] - (tests)) - (reset! mock-game nil)) diff --git a/backend/src/api/handler.clj b/backend/src/api/handler.clj index 5cb051a..a07f9ac 100644 --- a/backend/src/api/handler.clj +++ b/backend/src/api/handler.clj @@ -18,7 +18,9 @@ game-id player-id (parse-int (:index action)) - (parse-int (:row action)))) + (parse-int (:row action)) + [:rows (parse-int (:targetrownum action)) + :cards (parse-int (:targetindex action))])) (defroutes ^:private app-routes (context "/games" [] (defroutes game-list-routes diff --git a/backend/src/rules/count_cards.clj b/backend/src/rules/count_cards.clj index 10465b3..87c5ab3 100644 --- a/backend/src/rules/count_cards.clj +++ b/backend/src/rules/count_cards.clj @@ -1,7 +1,7 @@ (ns rules.count-cards) (defn count-cards - "Count all cards that has keys as in condition an sums their summand" + "Count (or sums the summands of) all cards that have keys as in condition " [game-state condition & summand] (let [k (vec (keys condition)) summand (first summand)] diff --git a/backend/test/api/join_game_test.clj b/backend/test/api/base_test.clj similarity index 80% rename from backend/test/api/join_game_test.clj rename to backend/test/api/base_test.clj index 8da34fe..a2ce642 100644 --- a/backend/test/api/join_game_test.clj +++ b/backend/test/api/base_test.clj @@ -1,4 +1,4 @@ -(ns api.join-game-test +(ns api.base-test (:require [expectations.clojure.test :refer :all] [clojure.test :as ctest] [mocking :as mocking] @@ -8,6 +8,12 @@ (ctest/use-fixtures :each mocking/mock-persistence) +(defexpect game-creation + (expect 0 (:game-id (base/create-game))) + (expect messages/no-opp (:status (base/create-game))) + (expect nil (:player-ids (base/create-game))) + (expect true (contains? (base/create-game) :player-id))) + (defexpect join-game (let [joined-game (-> (base/create-game) :game-id base/add-player)] diff --git a/backend/test/api/create_game_test.clj b/backend/test/api/create_game_test.clj deleted file mode 100644 index a7a307d..0000000 --- a/backend/test/api/create_game_test.clj +++ /dev/null @@ -1,14 +0,0 @@ -(ns api.create-game-test - (:require [expectations.clojure.test :refer :all] - [clojure.test :as ctest] - [mocking :as mocking] - [api.base :as base] - [configs.messages :as messages])) - -(ctest/use-fixtures :each mocking/mock-persistence) - -(defexpect game-creation - (expect 0 (:game-id (base/create-game))) - (expect messages/no-opp (:status (base/create-game))) - (expect nil (:player-ids (base/create-game))) - (expect true (contains? (base/create-game) :player-id))) diff --git a/CONTRIBUTING.md b/docs/CONTRIBUTING.md similarity index 68% rename from CONTRIBUTING.md rename to docs/CONTRIBUTING.md index 58147a4..1769a00 100644 --- a/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,8 +1,50 @@ -# Project architecture +# Contributing + +This document is intended to give guidelines for those who are willing to contribute in the development of TCG. +It is divided in three parts: +- **Installation and usage** (how to prepare your computer for locally running the game and tests) +- **Project architecture** (which tools we use, and why) +- **Project structure** (how is the project organized) +- **Development practices** (what is expected from you as a collaborator when programming TCG) + +## Installation and usage + +You'll need to have the repository locally cloned: `git clone https://github.com/kenan-rhoton/card-game` + +### Docker + +You'll need to **install [Docker](https://store.docker.com/search?type=edition&offering=community)**. + +### Usage + +`docker-compose build && docker-compose up` + +### Tests + +While working on backend stuff (Clojure), please keep a terminal open at *all* times with the following command running: + +`docker-compose run backend lein test-refresh` + +While working on frontend stuff (Javascript), please keep a terminal open at *all* times with the following command running: + +`docker-compose run frontend yarn test-refresh` + +This will give you instant feedback through the tests. + +If you don't want to use docker (and have Leiningen/Yarn installed), you can use the non-docker versions of the commands, which **must** be executed from within the respective directories (`backend`and `frontend` respectively): + +`lein test-refresh` +`yarn test-refresh` + +To run *all* tests, use: + +`bash fulltest.sh` + +## Project architecture The project is divided (as of now) into two main sections: *backend* and *frontend*, each with their quirks. -## Backend architecture +### Backend architecture We use [Clojure](https://www.braveclojure.com) as the backend language for pretty much **everything** due to basically two reasons: @@ -13,11 +55,11 @@ The backend also uses [Redis](https://redis.io) as a key-value storage mechanism Finally, the backend uses [Compojure](https://github.com/weavejester/compojure) to define it's [REST API](http://www.restapitutorial.com), which is the way the *frontend* will communicate with it. -## Frontend architecture +### Frontend architecture Frontend uses a standard [Vue.js](https://vuejs.org) architecture due to being easy to set up and not overcomplicating the frontend aspects. -## Docker +### Docker We also use [Docker](https://docs.docker.com) to launch everything. Why? @@ -29,7 +71,7 @@ And how does it work? Learn this and much more by [RTFM](https://docs.docker.com/engine/docker-overview/)! :D -# Project structure +## Project structure The structure of a project (where the f*** is that file?) might be more important than it's architecture. In this case, there is a three-way split: *backend* and *frontend* as before, but we also have de *e2e* tests to worry about. @@ -40,16 +82,16 @@ But some things also happen at the root: However, we will understand this further in the following sections. -## Backend structure +### Backend structure - **backend/Dockerfile**: Defines how the Docker image for the backend will be built and run - **backend/project.clj**: Defines the project dependencies and entry point -- **backend/test/card_game/**: Contains all the unit tests for the code. Remember that a unit test must be done *before* the actual code. -- **backend/src/card_game/**: Contains the code that will run in production, the actual logic. -- **backend/src/card_game/persistence.clj**: This is the only file to interact directly with the database. All database calls *must* pass through here. -- **backend/src/card_game/api_handler.clj**: This is the only file to interact directly with frontend. Any actions to take as a response to a frontend call *must* be defined here. +- **backend/test/**: Contains all the unit tests for the code, following the same structure as src/. Remember that a unit test must be done *before* the actual code. +- **backend/src/rules**: Contains the code that will run in production, the actual logic. +- **backend/src/persistence/persistence.clj**: This is the only file to interact directly with the database. All database calls *must* pass through here. +- **backend/src/api/handler.clj**: This is the only file to interact directly with frontend. Any actions to take as a response to a frontend call *must* be defined here. -## Frontend structure +### Frontend structure - **frontend/Dockerfile** and **frontend/entry.sh**: Defines the Docker image and its entrypoint. - **frontend/package.json** and **frontend/yarn.lock**: Define the project dependencies (`yarn.lock` is autogenerated by `yarn`) @@ -62,7 +104,7 @@ However, we will understand this further in the following sections. - **frontend/src/components/** and **frontend/src/views**: The application logic, separated into "views" and "components" following no good criteria as of yet, we will improve on this in the future. -# Contributing guidelines +## Development practices For any change or contribution, this is what is expected of you: @@ -84,7 +126,8 @@ We will value the following things on your contribution *in this order*: If at any point you have a question, please ask it if possible through a comment so others may benefit from the answer. -# Other notes +### Other notes 1. We use a strict [TDD](http://www.javiersaldana.com/tech/2014/11/26/refactoring-the-three-laws-of-tdd.html) discipline to contribute to this project, and we expect at *least* that level of tests from any contribution. If we believe the tests don't cover enough production cases, you will be asked to review your code. -2. We always merge through `Squash & Merge`, which will cause you conflicts if you make a pull request from your personal fork's master branch. We will warn you about this if we see it, as we think it's much more convenient to use your master branch *purely* to be up to date with ours and to make a branch for each feature. +2. All merges should be done to the *develop* branch. There, e2e tests are not ensure to work correctly. That allows us to work in parallel on *backend* and *frontend*. When e2e passes on *develop*, a merge is done to *master*. +3. We always merge through `Squash & Merge`, which will cause you conflicts if you make a pull request from your personal fork's master branch. We will warn you about this if we see it, as we think it's much more convenient to use your master branch *purely* to be up to date with ours and to make a branch for each feature. diff --git a/LICENSE b/docs/LICENSE similarity index 100% rename from LICENSE rename to docs/LICENSE diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..419fced --- /dev/null +++ b/docs/README.md @@ -0,0 +1,30 @@ +# TCG - Troll Card Game + +## What's this project? + +In early 2018 a group of friends decided to begin the creation of an online card game. + +Every design aspect of the game is discussed and decided along the way. +Most discussion of the game design is done through the Discord channel and conclusions are registered on the Wiki. + +## Contributing + +There are two main ways to contribute to this project. +- **Programming**: Everything on how to contribute developing the game is explained in `docs/CONTRIBUTING.md`. +- **Designing**: All design discussion is done through the Discord channel in catalan (though we might change to spanish). To have access to the Discord channel, send a message to Masclins#8514. + +In a near future, there will be a third way: +- **Testing**: When the game is in a state that allows testing, anybody willing to play it will be really helpful. We'll give guidelines on how to do so. + +## Usage + +This is (or will be) an online game run on a server and played through browser (at least at the beginning). That means that you'll need nothing other than a browser for playing it. +The website for playing the game will be given as soon as we have a version worth playing. + +For developers, instructions on how to install and run the game are given on `docs/CONTRIBUTING.md`. + +## License + +Copyright © 2018 Kenan Rhoton + +Distributed under the MIT License. \ No newline at end of file diff --git a/frontend/src/game/board/board.js b/frontend/src/game/board/board.js index f789abb..ca4cc11 100644 --- a/frontend/src/game/board/board.js +++ b/frontend/src/game/board/board.js @@ -19,9 +19,10 @@ module.exports = { }) boardState.forEach(function (row, rownum) { - row["cards"].forEach(function (cardInRow) { + row["cards"].forEach(function (cardInRow, index) { var newCard = builder.buildCard(templates.baseCard, cardInRow); newCard.setAttribute("rownum", rownum); + newCard.setAttribute("index", index); if (cardInRow["owner"] === "me") { fetchRow("#my-rows .game-row", rownum).appendChild(newCard); @@ -29,6 +30,7 @@ module.exports = { fetchRow("#opp-rows .game-row", rownum).appendChild(newCard); } }); + document.querySelectorAll("#limits .scores-row")[rownum].innerText = "(lim: " + row["limit"] + ")" }); }, diff --git a/frontend/src/game/board/builder.js b/frontend/src/game/board/builder.js index 91f8089..3593669 100644 --- a/frontend/src/game/board/builder.js +++ b/frontend/src/game/board/builder.js @@ -46,7 +46,8 @@ module.exports = { if (status.clickedCard && status.clickedCard.hasAttribute("row-played") && !status.clickedCard.hasAttribute("target")) { - status.clickedCard.setAttribute("target", 1); + status.clickedCard.setAttribute("target", + [this.getAttribute("rownum"), this.getAttribute("index")]); play.playCard(status.clickedCard); } }); diff --git a/frontend/src/game/play/hand.js b/frontend/src/game/play/hand.js index 0165141..7543909 100644 --- a/frontend/src/game/play/hand.js +++ b/frontend/src/game/play/hand.js @@ -21,6 +21,8 @@ module.exports = { status.clickedCard = card; card.style.background = "red"; } + + document.getElementById("game-status").innerHTML = config.messages["play"]; } }) } diff --git a/frontend/src/game/play/play.js b/frontend/src/game/play/play.js index 2a44630..30d0604 100644 --- a/frontend/src/game/play/play.js +++ b/frontend/src/game/play/play.js @@ -14,9 +14,14 @@ module.exports = { status.clickedCard = card; document.getElementById("game-status").innerHTML = "Select a target"; } else { + if (!card.hasAttribute("target")) { + card.setAttribute("target", [0, 0]); + } const playData = { index: card.getAttribute("index"), row: card.getAttribute("row-played"), + targetrownum: card.getAttribute("target")[0], + targetindex: card.getAttribute("target")[2], }; card.style.background = "green"; diff --git a/frontend/tests/game/play.test.js b/frontend/tests/game/play.test.js index 0fc2b62..be77503 100644 --- a/frontend/tests/game/play.test.js +++ b/frontend/tests/game/play.test.js @@ -12,11 +12,12 @@ test('Playing cards changes background as intended', () => { play.playCard(card); expect(card.style.background).toBe("green"); + card = document.createElement("div"); card.setAttribute("add-power", 1); play.playCard(card); expect(card.style.background).toBe("yellow"); - card.setAttribute("target", 1); + card.setAttribute("target", "any-string-works-as-target"); play.playCard(card); expect(card.style.background).toBe("green"); });