diff options
-rw-r--r-- | pages/search.tsx | 1 | ||||
-rw-r--r-- | posts/po4-api.md | 105 | ||||
-rw-r--r-- | posts/po4-voerbak.md | 81 | ||||
-rw-r--r-- | posts/po4.md | 137 | ||||
-rwxr-xr-x | scripts/meta | 10 | ||||
-rwxr-xr-x | scripts/postinfo | 2 | ||||
-rw-r--r-- | todo.todo | 2 |
7 files changed, 334 insertions, 4 deletions
diff --git a/pages/search.tsx b/pages/search.tsx index af9bfeb..a0eb32c 100644 --- a/pages/search.tsx +++ b/pages/search.tsx @@ -13,6 +13,7 @@ function SearchBar(props: { searchFunction: () => void }) { id="searchInput" placeholder="Search for posts..." onChange={() => props.searchFunction()} + spellCheck="false" autoComplete="off"/> <button className="button" onClick={() => props.searchFunction()}><SearchOutlinedIcon/></button> </div> diff --git a/posts/po4-api.md b/posts/po4-api.md new file mode 100644 index 0000000..0ca148b --- /dev/null +++ b/posts/po4-api.md @@ -0,0 +1,105 @@ +[meta]: <title> (po connect-4 api readme) +[meta]: <tags> (po4, po-connect-4, api, rest) +[meta]: <date> (April 1 2021) +[meta]: <author> (Loekaars) + +# API + +This is the subdirectory for the API. You can find the API reference in [this](https://docs.google.com/spreadsheets/d/1mDN9IUqRIMjr_9RmLxKybjIgVuaUadalmPEFnG-XeJg/edit?usp=sharing) Google Docs document. + +## Endpoint reference (WIP) + +API return type classes are mostly defined in api/api.ts + +endpoint|method|description|parameters|authorization +-|-|-|-|- +/status | GET | get online user count and active game count +/auth/login | POST | log in with email or username +/auth/token | POST | log in using a token (stored as cookie) +/auth/signup | POST | sign up +/user/info | GET\|POST | get user info by username or id note: avatar is a uri to a 256x256 .png image +/user/games | GET\|POST | get games of user +/user/avatar | GET\|POST | fetch or update avatar note: avatar is a client-resized 256x256 .png base64-encoded image, request returns error when image is not .png or larger than 256x256 +/user/prefrences | GET\|POST | fetch or change user preferences +/user/password | POST | update password +/user/email | POST | update email (token used for authentication if password is undefined) +/user/username | POST | update username (token used for authentication if password is undefined) +/user/status | POST | update status +/user/searchFriends | POST | search user's friend list +/social/request | POST | send a friend request to a user by user id +/social/accept | POST | accept a friend request +/social/remove | POST | remove a friend from your friend list or delete a friend request from a user +/social/search | POST | search for users by username or status +/social/block | POST | block a user +/social/unblock | POST | unblock a user +/social/list/requests | GET | get a list of unaccepted friend requests +/social/list/blocks | GET | get a list of blocked people +/social/list/friends | GET | get a list of your friends +/game/new | POST | create a new private game +/game/random | POST | join or create a public game +/game/info | POST | +/game/accept | POST | accept game invite or rematch +/game/spectate | POST | spectate a game by id + +## Events + +These are events that are fired by the socket.io connection + +event|description|data|direction|context +-|-|-|-|- +fieldUpdate|recieve new playfield from server|`{ field: string }`|`s -> c`|game +turnUpdate|recieve if it's player 1's move|`{ player1: boolean }`|`s -> c`|game +gameStart|sent when game starts|`none`|`s -> c`|game +finish|sent when game finishes|`none`|`s -> c`|game +resign|send to resign, is then forwarded to all subscribed clients|`none`|`s <-> c`|game +newMove|send a new move|`{ move: int, game_id: string }`|`s <- c`|game +registerGameListener|listen to events for a game|`{ id: string }`|`s <- c`|game +incomingFriendRequest|get notified of friend request|`none`|`s -> c`|global +changedRelation|get notified of a different relation to someone|`{ id: string }`|`s -> c`|global + +## How to test API endpoints +```sh +# If you're running the standalone flask server: +curl http://localhost:5000/<endpoint> + +# If you're running flask and nginx at the same time: +curl http://localhost:2080/api/<endpoint> +``` + +## How to add new API endpoints + +Please follow these rules when creating new API endpoints: + +1. Endpoints should always return a valid JSON object and an appropriate [http code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) +2. Endpoints that are in a namespace should get their own directory in this folder, eg. http://localhost:5000/status is defined in api/status.py, http://localhost:5000/auth/signup is defined in api/auth/signup.py etc. +3. Endpoints that take data should verify that the data is present and valid, and return an empty JSON object with http code 400 (bad request) if the data isn't valid. +4. Endpoints that require database access should get the cursor/connection object from api/db.py + +## Example endpoint + +Here's a simple endpoint that returns an empty JSON object: + +```py +# api/tests/example.py +from flask import Blueprint + +example = Blueprint('example', __name__) + +@example.route('/example') +def index(): + # python dictionaries are automatically converted to JSON by flask + return {"hello": "world"}, 200 # flask returns http code 200 by default if no code is explicitly defined + +# define a `dynamic_route` variable at the end of your endpoint definition file +# dynamic_route[0] is the namespace +# dynamic_route[1] is your flask.Blueprint +dynamic_route = ["/tests", status] + +# this endpoint will be routed to /tests/example +# \___/ \_____/ +# | | +# | endpoint (defined by the @Blueprint.route() decorator) +# | +# namespace (defined in dynamic_route variable) +``` + diff --git a/posts/po4-voerbak.md b/posts/po4-voerbak.md new file mode 100644 index 0000000..99759b1 --- /dev/null +++ b/posts/po4-voerbak.md @@ -0,0 +1,81 @@ +[meta]: <title> (po connect-4 voerbak readme) +[meta]: <tags> (po4, po-connect-4, voerbak, c) +[meta]: <date> (April 1 2021) +[meta]: <author> (Loekaars) + +# Voerbak + +Here's the source for voerbak, this project's connect 4 engine. The name comes from an abbreviation for the Dutch word for connect 4: Vier Op Een Rij -> VOER + bak = voerbak + +Voerbak uses a 1-dimensional array for storing the playfield, and it's printed after every move. The ordering is left to right, then bottom to top: + +35|36|37|38|39|40|41 +-|-|-|-|-|-|- +28|29|30|31|32|33|34 +21|22|23|24|25|26|27 +14|15|16|17|18|19|20 +7|8|9|10|11|12|13 +0|1|2|3|4|5|6 + +Voerbak is used in this project using api/game/voerbak_connector.py + +## Building + +```sh +make +``` + +## Input + +Voerbak takes moves seperated by newlines from stdin. An example game would look like this: + +``` sh +echo "4,3,3,2,1,2,2,7,1,7,1,7,1" | sed "s/,/\n/g" | ./voerbak +# ^ convert "," to newline +``` + +## Output + +Voerbak outputs special messages in this format: + +``` +e:full +^ \__/ +| | +| message (without spaces) +| +message type +``` + +Message reference: + +type|name|messages +-|-|- +d|draw|full = board is full +e|errors|full = column is full +m|move|true|false = if it's player 1's move +w|win|int-int = board indices where 4 was connected + +## Command-line arguments + +```sh +$ ./voerbak --help +Usage: voerbak [OPTION...] arguments +Connect 4 engine + + -c, --solver=NAME Solver used for computing moves (unset is two + humans playing) + -h, --height=HEIGHT Field height (rows) + -v, --verbosity=LEVEL Verbosity, 0 = none (default), 1 = info, 2 = + debug + -w, --width=WIDTH Field width (columns) + -?, --help Give this help list + --usage Give a short usage message + -V, --version Print program version + +Mandatory or optional arguments to long options are also mandatory or optional +for any corresponding short options. + +Report bugs to https://github.com/lonkaars/po-4-op-een-rij/. +``` + diff --git a/posts/po4.md b/posts/po4.md new file mode 100644 index 0000000..c9770dc --- /dev/null +++ b/posts/po4.md @@ -0,0 +1,137 @@ +[meta]: <title> (po connect-4 readme) +[meta]: <tags> (po4, po-connect-4, readme, github) +[meta]: <date> (April 1 2021) +[meta]: <author> (Loekaars) + +# PO connect-4 + +![](./banner.png) + +<p align="center"> +<img src="https://img.shields.io/github/license/lonkaars/po-4-op-een-rij"/> +<img src="https://img.shields.io/github/languages/count/lonkaars/po-4-op-een-rij"/> +<img src="https://img.shields.io/static/v1?label=platform&message=linux"/> +</p> + +> Some of this project's code is in Dutch (commit messages, documents etc.), +along with the whole website. This was originally a school project, but I'm +going to keep maintaining this project during my exams and summer break + +## Planned features: + +- [x] working connect 4 game +- [x] client-server connection with socket.io +- [x] account creation +- [ ] anonymous accounts +- [x] invite links +- [x] safe password authentication +- [ ] play against the computer +- [x] follow people/add as friend +- [ ] game rating like on chess.com +- [x] rest api that handles all of this instead of some janky solution +- [ ] Messages +- [ ] Multiple game modes +- [ ] Themes +- [ ] Animations + +## Used libraries and frameworks: + +- [Flask](https://flask.palletsprojects.com/) for the REST API +- [ReactJS](https://reactjs.org/) to create the website +- [NextJS](https://nextjs.org/) for static react pages and html page routing +- [socket.io](https://socket.io/) for bidirecitonal communication during a game +- [SQLite](https://sqlite.org/index.html) for the database +- [nginx](https://nginx.org/en/) for serving static files generated by nextjs, caching and reverse proxy + +A design prototype of the website can be found on +[Figma](https://www.figma.com/file/rTciVQApAe6cwrH1Prl5Wn/4-op-een-rij?node-id=0%3A1). +An outdated version of the API documentation is still on Google Docs, but I'm +moving and updating it to be in api/readme.md. + +![](./diagram.png) + +## setup + +To set up this project you'll need to install npm and pip dependencies, pull +all git submodules and compile voerbak and the sql extensions. + +> I haven't figured out how to run this project on Windows, so please install +> [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10) if you want +> to run this yourself on Windows. The distro you choose doesn't matter, though +> package names in ./configure may vary if your distro doesn't use the apt +> package manager. + +### automatic setup using `./configure` (debian/ubuntu) + +This script might also work on other distro's using the `apt` package manager. +To start the setup process you only need to run the following command: + +```sh +./configure +``` + +The script calls sudo and apt install so some password input/manual +confirmation is required, but most of the install should be automated. + +### manual setup (other distro's) + +If your disto doesn't use the `apt` package manager, you can still run this +project by following these steps: + +0. `git clone https://github.com/lonkaars/po-4-op-een-rij` +1. Make sure you have [python](https://python.org/downloads) (with pip and venv) installed. +2. Make sure you have [nodejs](https://nodejs.org/en/download) (with npm) installed. +3. Make sure you have [nginx](https://nginx.org/en/) installed. +4. Make sure you have [make](https://www.gnu.org/software/make/) and the gnu c compilers [gcc](https://gcc.gnu.org/) installed (most distro's will have these by default). +5. Install typescript, react-scripts and yarn: + ```sh + npm i -g typescript yarn + ``` +6. Create a new python virtual environment and install pip modules: + ```sh + python -m venv venv + source venv/bin/activate + pip install -r requirements.txt + ``` +7. Install node modules: + ```sh + yarn + ``` +8. Build voerbak: + ```sh + cd voerbak + make + ``` +9. Download submodules: + ```sh + git submodule init + git submodule update + ``` +10. Initialize database and build SQL extensions: + ```sh + cd database + ./init_db.sh + make + ``` + +## How to start + +In order to start this project you'll need three terminal windows to start the +flask server, react server, and nginx seperately: + +```sh +# term 1 +source venv/bin/activate +python3 api/main.py + +# term 2 +yarn dev + +# term 3 +sudo nginx -c $PWD/nginx.conf + +# if nginx can't run as the user nobody, try running the following command and restart nginx: +# this command is also in ./configure +sed "s/user nobody/user $(whoami)/" -i nginx.conf +``` + diff --git a/scripts/meta b/scripts/meta index f33ea3d..e869d0b 100755 --- a/scripts/meta +++ b/scripts/meta @@ -11,8 +11,12 @@ if [[ $tag_name = "tags" ]]; then sed -z '$ s/\n$//' |\ jq --raw-input --slurp 'split("\n")' else - echo $output |\ - sed -z '$ s/\n$//' |\ - jq --raw-input + if [[ $output = "" ]]; then + echo "" | jq --raw-input + else + echo $output |\ + sed -z '$ s/\n$//' |\ + jq --raw-input + fi fi diff --git a/scripts/postinfo b/scripts/postinfo index 94827f1..72c6526 100755 --- a/scripts/postinfo +++ b/scripts/postinfo @@ -3,7 +3,7 @@ filename=$1 jq -n \ - --argjson title "$(./meta title $filename)" \ + --argjson title "$(./meta title $filename || '\n')" \ --argjson subtitle "$(./meta subtitle $filename)" \ --argjson author "$(./meta author $filename)" \ --argjson date "$(./meta date $filename)" \ diff --git a/todo.todo b/todo.todo new file mode 100644 index 0000000..846ba50 --- /dev/null +++ b/todo.todo @@ -0,0 +1,2 @@ +- gh markdown parsing (code highlighting + checkbox lists + html parsing) +- ignore lines starting with '#' in code blocks |