Compare commits

..

No commits in common. 'main' and 'master' have entirely different histories.
main ... master

@ -1,57 +0,0 @@
# Xquisite Branch
A branching version of the [exquisite corpse](https://en.wikipedia.org/wiki/Exquisite_corpse) game. A drawing app developed for [SI17](https://issue.xpub.nl/17/).
Draw something, upload it and send the link to someone else: they will continue from your drawing. But wait! There's a catch!!!!! If you send to just one person the chain will continue linearly, but send it to more people and things will start branching in different directions.
## Install
Clone the repository.
```
git clone https://git.xpub.nl/kamo/exquisite-branch.git
```
Create a virtual environment.
```
python3 -m venv venv
```
Install the requirements with `pip` and the `requirements.txt` file.
```
pip install -r requirements.txt
```
Create an `.env` file in the root folder of the project with the following variables:
```
DEBUG=True
FLASK_ENV=development
FLASK_APP=exquisite_branch
```
Before running the app for the first time, be sure to initialize the database. __Watch out:__ this will delete the previous instance of the database along with its contents!
```
flask init-db
```
After initializing the database you can run the flask application
```
flask run
```
## Overview
_Xquisite Branch_ saves contents in a database, and join them together in a branching version of the exquisite corpse.
The original exquisite corpse data structure is something similar to a linked list, where every drawing is connected to the previous one. Contents in _Xquisite Branch_ are saved in a database with the same principle.
Each entry in the database has the following properties:
- `id`: a unique identifier for every entry
- `branch`: a random name for the excerpt
- `parent`: the random name of the previous excerpt
- `content`: the actual content of the writings
- `username`: the author of the excerpt
When generating the display page, every entry look up its `parent` property to position itself after that.
Mhh should rewrite this better bc is super convoluted ahah.

@ -1,7 +1,6 @@
import os import os
from flask import Flask, send_from_directory from flask import Flask, send_from_directory
from . import prefix from . import prefix
from flask_mako import MakoTemplates
def create_app(test_config=None): def create_app(test_config=None):
@ -28,8 +27,6 @@ def create_app(test_config=None):
from . import db from . import db
db.init_app(app) db.init_app(app)
mako = MakoTemplates(app)
@app.route("/favicon.ico") @app.route("/favicon.ico")
def favicon(): def favicon():
return send_from_directory( return send_from_directory(

@ -1,39 +1,12 @@
from flask import (Blueprint) from flask import (Blueprint, flash, g, redirect,
from flask_mako import render_template render_template, request, session, url_for)
from exquisite_branch.db import get_db from exquisite_branch.db import get_db
bp = Blueprint('display', __name__, url_prefix='/display') bp = Blueprint('display', __name__, url_prefix='/display')
# @bp.route('/')
# def display():
# db = get_db()
# branches = db.execute(
# "SELECT content, branch, parent, username FROM branches"
# ).fetchall()
# streams = []
# for branch in branches[::-1]:
# if branch not in flatten(streams):
# stream = [branch]
# parent = branch['parent']
# while parent != 'NEW':
# current = next(
# (x for x in branches if x['branch'] == parent), None)
# parent = current['parent']
# stream.append(current)
# streams.append(stream[::-1])
# return render_template('display_mako.html', branches=branches, streams=streams)
# def flatten(t):
# return [item for sublist in t for item in sublist]
@bp.route('/') @bp.route('/')
def display(): def display():
db = get_db() db = get_db()
@ -42,4 +15,21 @@ def display():
"SELECT content, branch, parent, username FROM branches" "SELECT content, branch, parent, username FROM branches"
).fetchall() ).fetchall()
return render_template('display_linked_mako.html', branches=branches) streams = []
for branch in branches[::-1]:
if branch not in flatten(streams):
stream = [branch]
parent = branch['parent']
while parent != 'NEW':
current = next(
(x for x in branches if x['branch'] == parent), None)
parent = current['parent']
stream.append(current)
streams.append(stream[::-1])
return render_template('display.html', branches=branches, streams=streams)
def flatten(t):
return [item for sublist in t for item in sublist]

@ -4,20 +4,7 @@ from flask import (Blueprint, flash, g, redirect,
from exquisite_branch.db import get_db from exquisite_branch.db import get_db
from werkzeug.exceptions import abort from werkzeug.exceptions import abort
import shortuuid from shortuuid import uuid
import uuid
def get_uuid(d=7):
'''return a short uuid (default 7 chars)'''
u = uuid.uuid4()
s = shortuuid.encode(u)
return s[:d]
bp = Blueprint('draw', __name__, url_prefix='/draw') bp = Blueprint('draw', __name__, url_prefix='/draw')
@ -44,8 +31,7 @@ def draw(parent=None):
print(url_for('share.share', branch=f"{branch}")) print(url_for('share.share', branch=f"{branch}"))
return redirect(url_for('share.share', branch=branch)) return redirect(url_for('share.share', branch=branch))
branch = get_uuid() branch = uuid()
previous = db.execute( previous = db.execute(
"SELECT content, branch, parent FROM branches" "SELECT content, branch, parent FROM branches"
@ -62,7 +48,7 @@ def draw(parent=None):
@bp.route('/last', methods=('GET', 'POST')) @bp.route('/last', methods=('GET', 'POST'))
def last(): def last():
branch = get_uuid() branch = uuid()
db = get_db() db = get_db()
previous = db.execute( previous = db.execute(
'SELECT * FROM branches ORDER BY id DESC LIMIT 1' 'SELECT * FROM branches ORDER BY id DESC LIMIT 1'
@ -88,7 +74,7 @@ def last():
@bp.route('/', methods=('GET', 'POST')) @bp.route('/', methods=('GET', 'POST'))
def new(): def new():
db = get_db() db = get_db()
branch = get_uuid() branch = uuid()
parent = 'NEW' parent = 'NEW'
if request.method == 'POST': if request.method == 'POST':

@ -1,52 +0,0 @@
.container{
display: block;
padding: 2000px;
}
.streams {
overflow-x: auto;
overflow-y: hidden;
position: relative;
width: 500px;
height: 500px;
display: inline-block;
}
.stream {
white-space: nowrap;
position: relative;
display: inline-block;
width: 500px;
height: 500px;
position: relative;
}
.svg-container {
position: absolute;
top: 0;
left: 0;
display: inline-block;
}
.author {
position: absolute;
left: 50%;
bottom: 50px;
font-size: 1rem;
background-color: white;
}
.branches {
overflow-x: auto;
overflow-y: hidden;
}
.branch {
white-space: nowrap;
}
.branch svg {
border-top: 1px solid currentColor;
}

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Exquisite Branch</title>
<link rel="stylesheet" href="${url_for('static', filename='css/variables.css')}" />
<link rel="stylesheet" href="${url_for('static', filename='css/global.css')}" />
<%block name='head' %></%block>
</head>
<body>
<nav>
<%block name='nav' >
<a href="${url_for('home.home')}">Home</a>
<a href="${url_for('display.display')}">Results</a>
</%block>
</nav>
${self.body()}
</body>
</html>

@ -1,46 +0,0 @@
<%inherit file="base_mako.html" />
<%block name="head">
<link rel="stylesheet" href="${url_for('static', filename='css/display_mako.css')}">
</%block>
<main class="container">
<% from random import random %>
<% from collections import defaultdict %>
<% transform = {'NEW': ''} %>
<% visited = defaultdict(int) %>
<div class="stream">
% for branch in branches:
<% visited[branch['parent']] += 1 %>
% if visited[branch['parent']] > 1:
<% steer = (random() - 0.5) * 0.25 %>
% else:
<% steer = 0 %>
% endif
<% transform[branch['branch']] = f'{transform[branch["parent"]]} rotate({random() * 0.04 + steer}turn) translateX(100%)' %>
<div class="svg-container" style="transform: ${transform[branch['parent']]}">
<a href="${url_for('draw.draw', parent=branch['branch'], _external=True, _scheme='https')}" target="__blank">
${branch['content']}
</a>
</div>
% endfor
</div>
</main>

@ -1,18 +0,0 @@
<%inherit file="base_mako.html" />
<%block name="head">
<link rel="stylesheet" href="${url_for('static', filename='css/display_mako.css')}">
</%block>
<% from random import random %>
<% offset = 1 / (len(streams) + 1)%>
% for stream in streams:
<div class="stream">
<% transform = f'rotate({offset * loop.index}turn) translateX(100%) ' %>
% for branch in stream:
<% transform = transform + ' rotate(' + str((random() * 2 - 1) * 0.02) + 'turn) translateX(100%)'%>
<div class="svg-container" style="transform: ${transform}">${branch['content']}</div>
% endfor
</div>
% endfor

@ -8,20 +8,6 @@
<link rel="stylesheet" href="{{url_for('static', filename='css/variables.css')}}" /> <link rel="stylesheet" href="{{url_for('static', filename='css/variables.css')}}" />
<link rel="stylesheet" href="{{url_for('static', filename='css/global.css')}}" /> <link rel="stylesheet" href="{{url_for('static', filename='css/global.css')}}" />
<link rel="stylesheet" href="{{url_for('static', filename='css/home.css')}}" /> <link rel="stylesheet" href="{{url_for('static', filename='css/home.css')}}" />
<style>
.renovation
{
background-color: yellow;
display: inline-block;
transform: translateY(-90px) rotate(10deg);
padding: 8px;
font-size: 0.88rem;
font-family: 'Brush Script MT', cursive;
}
</style>
</head> </head>
<body> <body>
<header class="title"> <header class="title">
@ -31,7 +17,6 @@
></object> ></object>
<h1>really exquisite indeed</h1> <h1>really exquisite indeed</h1>
<span class='renovation'>RENOVATION IN PROGRESS!</span>
</header> </header>
<main> <main>
<a href="{{url_for('draw.new')}}">Start new</a> <br /> <a href="{{url_for('draw.new')}}">Start new</a> <br />

@ -1,15 +0,0 @@
autopep8==1.6.0
click==8.0.3
colorama==0.4.4
-e git+https://git.xpub.nl/kamo/exquisite-branch.git@ae185baf0c048ac5f9171314ea5e842362b99dcd#egg=exquisite_branch
Flask==2.0.2
Flask-Mako==0.4
itsdangerous==2.0.1
Jinja2==3.0.3
Mako==1.2.0
MarkupSafe==2.0.1
pycodestyle==2.8.0
python-dotenv==0.19.2
shortuuid==1.0.8
toml==0.10.2
Werkzeug==2.0.3

@ -9,7 +9,6 @@ setup(
install_requires=[ install_requires=[
'flask', 'flask',
'shortuuid', 'shortuuid',
'python-dotenv', 'python-dotenv'
'flask-mako'
], ],
) )

Loading…
Cancel
Save