aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <l.leblansch@gmail.com>2021-04-01 14:33:30 +0200
committerlonkaars <l.leblansch@gmail.com>2021-04-01 14:33:30 +0200
commit7d2c52b21ff28c80d28a1408cf6abb85d7725848 (patch)
tree2abdf8abdb7a5dac3ec3df36d497431283f86397
parentd2d813c04ce37cdb4a283dcd60b7986882970be5 (diff)
added po-connect-4 markdown files for testing + todo
-rw-r--r--pages/search.tsx1
-rw-r--r--posts/po4-api.md105
-rw-r--r--posts/po4-voerbak.md81
-rw-r--r--posts/po4.md137
-rwxr-xr-xscripts/meta10
-rwxr-xr-xscripts/postinfo2
-rw-r--r--todo.todo2
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