Compare commits
No commits in common. "946a740d4aecdd0963492761e8b9b54bb5b3367c" and "e061cdf04a201412ebdb53f5af4cfd5be7b86508" have entirely different histories.
946a740d4a
...
e061cdf04a
207
.gitignore
vendored
|
@ -1,207 +0,0 @@
|
||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
__pycache__/
|
|
||||||
*.py[codz]
|
|
||||||
*$py.class
|
|
||||||
|
|
||||||
# C extensions
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Distribution / packaging
|
|
||||||
.Python
|
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
downloads/
|
|
||||||
eggs/
|
|
||||||
.eggs/
|
|
||||||
lib/
|
|
||||||
lib64/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
wheels/
|
|
||||||
share/python-wheels/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
MANIFEST
|
|
||||||
|
|
||||||
# PyInstaller
|
|
||||||
# Usually these files are written by a python script from a template
|
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
||||||
*.manifest
|
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
pip-delete-this-directory.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
htmlcov/
|
|
||||||
.tox/
|
|
||||||
.nox/
|
|
||||||
.coverage
|
|
||||||
.coverage.*
|
|
||||||
.cache
|
|
||||||
nosetests.xml
|
|
||||||
coverage.xml
|
|
||||||
*.cover
|
|
||||||
*.py.cover
|
|
||||||
.hypothesis/
|
|
||||||
.pytest_cache/
|
|
||||||
cover/
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
*.mo
|
|
||||||
*.pot
|
|
||||||
|
|
||||||
# Django stuff:
|
|
||||||
*.log
|
|
||||||
local_settings.py
|
|
||||||
db.sqlite3
|
|
||||||
db.sqlite3-journal
|
|
||||||
|
|
||||||
# Flask stuff:
|
|
||||||
instance/
|
|
||||||
.webassets-cache
|
|
||||||
|
|
||||||
# Scrapy stuff:
|
|
||||||
.scrapy
|
|
||||||
|
|
||||||
# Sphinx documentation
|
|
||||||
docs/_build/
|
|
||||||
|
|
||||||
# PyBuilder
|
|
||||||
.pybuilder/
|
|
||||||
target/
|
|
||||||
|
|
||||||
# Jupyter Notebook
|
|
||||||
.ipynb_checkpoints
|
|
||||||
|
|
||||||
# IPython
|
|
||||||
profile_default/
|
|
||||||
ipython_config.py
|
|
||||||
|
|
||||||
# pyenv
|
|
||||||
# For a library or package, you might want to ignore these files since the code is
|
|
||||||
# intended to run in multiple environments; otherwise, check them in:
|
|
||||||
# .python-version
|
|
||||||
|
|
||||||
# pipenv
|
|
||||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
||||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
||||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
||||||
# install all needed dependencies.
|
|
||||||
#Pipfile.lock
|
|
||||||
|
|
||||||
# UV
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
||||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
||||||
# commonly ignored for libraries.
|
|
||||||
#uv.lock
|
|
||||||
|
|
||||||
# poetry
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
||||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
||||||
# commonly ignored for libraries.
|
|
||||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
||||||
#poetry.lock
|
|
||||||
#poetry.toml
|
|
||||||
|
|
||||||
# pdm
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
||||||
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
||||||
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
||||||
#pdm.lock
|
|
||||||
#pdm.toml
|
|
||||||
.pdm-python
|
|
||||||
.pdm-build/
|
|
||||||
|
|
||||||
# pixi
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
||||||
#pixi.lock
|
|
||||||
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
||||||
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
||||||
.pixi
|
|
||||||
|
|
||||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
||||||
__pypackages__/
|
|
||||||
|
|
||||||
# Celery stuff
|
|
||||||
celerybeat-schedule
|
|
||||||
celerybeat.pid
|
|
||||||
|
|
||||||
# SageMath parsed files
|
|
||||||
*.sage.py
|
|
||||||
|
|
||||||
# Environments
|
|
||||||
.env
|
|
||||||
.envrc
|
|
||||||
.venv
|
|
||||||
env/
|
|
||||||
venv/
|
|
||||||
ENV/
|
|
||||||
env.bak/
|
|
||||||
venv.bak/
|
|
||||||
|
|
||||||
# Spyder project settings
|
|
||||||
.spyderproject
|
|
||||||
.spyproject
|
|
||||||
|
|
||||||
# Rope project settings
|
|
||||||
.ropeproject
|
|
||||||
|
|
||||||
# mkdocs documentation
|
|
||||||
/site
|
|
||||||
|
|
||||||
# mypy
|
|
||||||
.mypy_cache/
|
|
||||||
.dmypy.json
|
|
||||||
dmypy.json
|
|
||||||
|
|
||||||
# Pyre type checker
|
|
||||||
.pyre/
|
|
||||||
|
|
||||||
# pytype static type analyzer
|
|
||||||
.pytype/
|
|
||||||
|
|
||||||
# Cython debug symbols
|
|
||||||
cython_debug/
|
|
||||||
|
|
||||||
# PyCharm
|
|
||||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
||||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
||||||
#.idea/
|
|
||||||
|
|
||||||
# Abstra
|
|
||||||
# Abstra is an AI-powered process automation framework.
|
|
||||||
# Ignore directories containing user credentials, local state, and settings.
|
|
||||||
# Learn more at https://abstra.io/docs
|
|
||||||
.abstra/
|
|
||||||
|
|
||||||
# Visual Studio Code
|
|
||||||
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
||||||
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
||||||
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
||||||
# you could uncomment the following to ignore the entire vscode folder
|
|
||||||
# .vscode/
|
|
||||||
|
|
||||||
# Ruff stuff:
|
|
||||||
.ruff_cache/
|
|
||||||
|
|
||||||
# PyPI configuration file
|
|
||||||
.pypirc
|
|
||||||
|
|
||||||
# Cursor
|
|
||||||
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
||||||
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
||||||
# refer to https://docs.cursor.com/context/ignore-files
|
|
||||||
.cursorignore
|
|
||||||
.cursorindexingignore
|
|
||||||
|
|
||||||
# Marimo
|
|
||||||
marimo/_static/
|
|
||||||
marimo/_lsp/
|
|
||||||
__marimo__/
|
|
BIN
db.sqlite3
22
manage.py
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
"""Django's command-line utility for administrative tasks."""
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Run administrative tasks."""
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'shrinkinminkin.settings')
|
|
||||||
try:
|
|
||||||
from django.core.management import execute_from_command_line
|
|
||||||
except ImportError as exc:
|
|
||||||
raise ImportError(
|
|
||||||
"Couldn't import Django. Are you sure it's installed and "
|
|
||||||
"available on your PYTHONPATH environment variable? Did you "
|
|
||||||
"forget to activate a virtual environment?"
|
|
||||||
) from exc
|
|
||||||
execute_from_command_line(sys.argv)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
137
requirements.txt
|
@ -1,137 +0,0 @@
|
||||||
appdirs==1.4.4
|
|
||||||
argcomplete==3.1.4
|
|
||||||
attrs==23.2.0
|
|
||||||
beautifulsoup4==4.12.3
|
|
||||||
blinker==1.7.0
|
|
||||||
bottle==0.12.25
|
|
||||||
Brlapi==0.8.5
|
|
||||||
Brotli==1.1.0
|
|
||||||
certifi==2023.11.17
|
|
||||||
chardet==5.2.0
|
|
||||||
click==8.1.6
|
|
||||||
colorama==0.4.6
|
|
||||||
command-not-found==0.3
|
|
||||||
configobj==5.0.8
|
|
||||||
contourpy==1.0.7
|
|
||||||
cryptography==41.0.7
|
|
||||||
cupshelpers==1.0
|
|
||||||
cycler==0.11.0
|
|
||||||
dbus-python==1.3.2
|
|
||||||
decorator==5.1.1
|
|
||||||
defer==1.0.6
|
|
||||||
defusedxml==0.7.1
|
|
||||||
deprecation==2.0.7
|
|
||||||
dill==0.3.8
|
|
||||||
distro==1.9.0
|
|
||||||
docker==5.0.3
|
|
||||||
eyed3==0.9.7
|
|
||||||
filelock==3.13.1
|
|
||||||
filetype==1.2.0
|
|
||||||
fonttools==4.46.0
|
|
||||||
fs==2.4.16
|
|
||||||
Glances==3.4.0.3
|
|
||||||
gyp==0.1
|
|
||||||
html2text==2024.2.26
|
|
||||||
httplib2==0.20.4
|
|
||||||
idna==3.6
|
|
||||||
ifaddr==0.2.0
|
|
||||||
IMDbPY==2021.4.18
|
|
||||||
influxdb==5.3.1
|
|
||||||
kiwisolver==0.0.0
|
|
||||||
launchpadlib==1.11.0
|
|
||||||
lazr.restfulclient==0.14.6
|
|
||||||
lazr.uri==1.0.6
|
|
||||||
libevdev==0.5
|
|
||||||
libvirt-python==10.0.0
|
|
||||||
louis==3.29.0
|
|
||||||
lxml==5.2.1
|
|
||||||
lz4==4.0.2+dfsg
|
|
||||||
Mako==1.3.2.dev0
|
|
||||||
Markdown==3.5.2
|
|
||||||
markdown-it-py==3.0.0
|
|
||||||
MarkupSafe==2.1.5
|
|
||||||
matplotlib==3.6.3
|
|
||||||
mdurl==0.1.2
|
|
||||||
mpmath==0.0.0
|
|
||||||
msgpack==1.0.3
|
|
||||||
multiprocess==0.70.16
|
|
||||||
mutagen==1.46.0
|
|
||||||
nemo-emblems==6.4.0
|
|
||||||
netaddr==0.8.0
|
|
||||||
netifaces==0.11.0
|
|
||||||
nicotine-plus==3.2.9
|
|
||||||
numpy==1.26.4
|
|
||||||
oauthlib==3.2.2
|
|
||||||
onboard==1.4.1
|
|
||||||
packaging==24.0
|
|
||||||
PAM==0.4.2
|
|
||||||
pexpect==4.9.0
|
|
||||||
pillow==10.2.0
|
|
||||||
pipx==1.4.3
|
|
||||||
platformdirs==4.2.0
|
|
||||||
ply==3.11
|
|
||||||
psutil==5.9.8
|
|
||||||
ptyprocess==0.7.0
|
|
||||||
pulsemixer==1.5.1
|
|
||||||
pyasn1==0.4.8
|
|
||||||
pyasyncore==1.0.2
|
|
||||||
pycairo==1.25.1
|
|
||||||
pycryptodomex==3.20.0
|
|
||||||
pycups==2.0.1
|
|
||||||
pycurl==7.45.3
|
|
||||||
pyelftools==0.30
|
|
||||||
Pygments==2.17.2
|
|
||||||
PyGObject==3.48.2
|
|
||||||
PyICU==2.12
|
|
||||||
pyinotify==0.9.6
|
|
||||||
PyJWT==2.7.0
|
|
||||||
PyNaCl==1.5.0
|
|
||||||
pyparsing==3.1.1
|
|
||||||
pyparted==3.12.0
|
|
||||||
pypng==0.20231004.0
|
|
||||||
pysmi==0.3.4
|
|
||||||
pysnmp==4.4.12
|
|
||||||
pystache==0.6.0
|
|
||||||
python-apt==2.7.7+ubuntu4
|
|
||||||
python-dateutil==2.8.2
|
|
||||||
python-debian==0.1.49+ubuntu2
|
|
||||||
python-gnupg==0.5.2
|
|
||||||
python-magic==0.4.27
|
|
||||||
python-xlib==0.33
|
|
||||||
pytz==2024.1
|
|
||||||
pyudev==0.24.0
|
|
||||||
pyxdg==0.28
|
|
||||||
PyYAML==6.0.1
|
|
||||||
qrcode==7.4.2
|
|
||||||
ranger-fm==1.9.3
|
|
||||||
repolib==2.2.1
|
|
||||||
requests==2.31.0
|
|
||||||
requests-file==1.5.1
|
|
||||||
rich==13.7.1
|
|
||||||
SciPy==1.11.4
|
|
||||||
setproctitle==1.3.3
|
|
||||||
setuptools==68.1.2
|
|
||||||
six==1.16.0
|
|
||||||
soupsieve==2.5
|
|
||||||
sympy==1.12
|
|
||||||
systemd-python==235
|
|
||||||
tinycss2==1.2.1
|
|
||||||
tldextract==3.1.2
|
|
||||||
typing_extensions==4.10.0
|
|
||||||
ubuntu-drivers-common==0.0.0
|
|
||||||
ufoLib2==0.16.0
|
|
||||||
ufw==0.36.2
|
|
||||||
ujson==5.9.0
|
|
||||||
unicodedata2==15.1.0
|
|
||||||
Unidecode==1.3.8
|
|
||||||
urllib3==2.0.7
|
|
||||||
userpath==1.9.1
|
|
||||||
wadllib==1.3.6
|
|
||||||
webencodings==0.5.1
|
|
||||||
websocket-client==1.7.0
|
|
||||||
websockets==10.4
|
|
||||||
wheel==0.42.0
|
|
||||||
xdg==5
|
|
||||||
xkit==0.0.0
|
|
||||||
xlrd==2.0.1
|
|
||||||
yt-dlp==2024.4.9
|
|
|
@ -1,16 +0,0 @@
|
||||||
"""
|
|
||||||
ASGI config for shrinkinminkin project.
|
|
||||||
|
|
||||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/5.2/howto/deployment/asgi/
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from django.core.asgi import get_asgi_application
|
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'shrinkinminkin.settings')
|
|
||||||
|
|
||||||
application = get_asgi_application()
|
|
|
@ -1,130 +0,0 @@
|
||||||
"""
|
|
||||||
Django settings for shrinkinminkin project.
|
|
||||||
|
|
||||||
Generated by 'django-admin startproject' using Django 5.2.3.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/5.2/topics/settings/
|
|
||||||
|
|
||||||
For the full list of settings and their values, see
|
|
||||||
https://docs.djangoproject.com/en/5.2/ref/settings/
|
|
||||||
"""
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
||||||
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
|
||||||
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
|
||||||
SECRET_KEY = 'django-insecure-)z5-$t&%njx^$4wrsq4+@#oybrssf_z*1(p9t(^o2v!2nkybab'
|
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
|
||||||
DEBUG = True
|
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['localhost', 'localhost:8000', '127.0.0.1']
|
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
|
||||||
'django.contrib.admin',
|
|
||||||
'django.contrib.auth',
|
|
||||||
'django.contrib.contenttypes',
|
|
||||||
'django.contrib.sessions',
|
|
||||||
'django.contrib.messages',
|
|
||||||
'django.contrib.staticfiles',
|
|
||||||
'web',
|
|
||||||
]
|
|
||||||
|
|
||||||
MIDDLEWARE = [
|
|
||||||
'django.middleware.security.SecurityMiddleware',
|
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
||||||
'django.middleware.common.CommonMiddleware',
|
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
||||||
]
|
|
||||||
|
|
||||||
ROOT_URLCONF = 'shrinkinminkin.urls'
|
|
||||||
|
|
||||||
TEMPLATES = [
|
|
||||||
{
|
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
||||||
'DIRS': [],
|
|
||||||
'APP_DIRS': True,
|
|
||||||
'OPTIONS': {
|
|
||||||
'context_processors': [
|
|
||||||
'django.template.context_processors.request',
|
|
||||||
'django.contrib.auth.context_processors.auth',
|
|
||||||
'django.contrib.messages.context_processors.messages',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
WSGI_APPLICATION = 'shrinkinminkin.wsgi.application'
|
|
||||||
|
|
||||||
|
|
||||||
# Database
|
|
||||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
|
||||||
'NAME': BASE_DIR / 'db.sqlite3',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Password validation
|
|
||||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
|
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# Internationalization
|
|
||||||
# https://docs.djangoproject.com/en/5.2/topics/i18n/
|
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
|
||||||
|
|
||||||
TIME_ZONE = 'UTC'
|
|
||||||
|
|
||||||
USE_I18N = True
|
|
||||||
|
|
||||||
USE_TZ = True
|
|
||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
|
||||||
# https://docs.djangoproject.com/en/5.2/howto/static-files/
|
|
||||||
|
|
||||||
STATIC_URL = 'static/'
|
|
||||||
STATIC_URL = '/static/'
|
|
||||||
STATIC_ROOT = BASE_DIR / 'staticfiles'
|
|
||||||
STATICFILES_DIRS = [BASE_DIR / 'static',]
|
|
||||||
STORAGES = {
|
|
||||||
"staticfiles": {
|
|
||||||
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
# Default primary key field type
|
|
||||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
|
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
|
@ -1,13 +0,0 @@
|
||||||
from django.contrib import admin
|
|
||||||
from django.urls import path
|
|
||||||
from web.views import index, album, socials, mailing_list
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
path('', index, name='index'),
|
|
||||||
path('album/', album, name='album'),
|
|
||||||
path('album.html/', album, name='album'),
|
|
||||||
path('socials/', socials, name='socials'),
|
|
||||||
path('socials.html/', socials, name='socials'),
|
|
||||||
path('mailing_list/', mailing_list, name='mailing_list'),
|
|
||||||
path('admin/', admin.site.urls),
|
|
||||||
]
|
|
|
@ -1,16 +0,0 @@
|
||||||
"""
|
|
||||||
WSGI config for shrinkinminkin project.
|
|
||||||
|
|
||||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'shrinkinminkin.settings')
|
|
||||||
|
|
||||||
application = get_wsgi_application()
|
|
7
static/css/bootstrap.min.css
vendored
|
@ -1,70 +0,0 @@
|
||||||
@font-face { font-family: Virgo; src: url('../fonts/virgo.ttf'); }
|
|
||||||
|
|
||||||
body {
|
|
||||||
background-color: #189ccf;
|
|
||||||
font-family: Virgo, monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-img {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 600px;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
|
||||||
margin-top: 20px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link {
|
|
||||||
width: 150px;
|
|
||||||
padding-right: 10px;
|
|
||||||
display: inline;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 45px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#band-img-1 {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iframe-container {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
width: 100%;
|
|
||||||
padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */
|
|
||||||
}
|
|
||||||
|
|
||||||
.responsive-iframe {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navi-link {
|
|
||||||
color: #ff0000;
|
|
||||||
padding-left: 10px;
|
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navi-link:hover {
|
|
||||||
opacity: 70%;
|
|
||||||
color: #ff0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-container {
|
|
||||||
color: #20d582;
|
|
||||||
background-color: #8220d5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-image {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 145 KiB |
Before Width: | Height: | Size: 242 KiB |
Before Width: | Height: | Size: 5.7 MiB |
Before Width: | Height: | Size: 47 KiB |
7
static/js/bootstrap.min.js
vendored
2
static/js/p5.min.js
vendored
|
@ -1,230 +0,0 @@
|
||||||
let myFont;
|
|
||||||
function preload() {
|
|
||||||
myFont = loadFont('assets/fonts/nabla.ttf');
|
|
||||||
}
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
var canvas = createCanvas(windowWidth, 200);
|
|
||||||
} else {
|
|
||||||
var canvas = createCanvas(windowWidth, 300);
|
|
||||||
}
|
|
||||||
canvas.parent('shrinkin-sketch')
|
|
||||||
}
|
|
||||||
|
|
||||||
function windowResized() {
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
var canvas = resizeCanvas(windowWidth, 200);
|
|
||||||
} else {
|
|
||||||
var canvas = resizeCanvas(windowWidth, 300);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Ball {
|
|
||||||
constructor(x, y, r) {
|
|
||||||
this.position = new p5.Vector(x, y);
|
|
||||||
this.velocity = p5.Vector.random2D();
|
|
||||||
this.velocity.mult(3);
|
|
||||||
this.r = r;
|
|
||||||
this.m = r * 0.1;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
update() {
|
|
||||||
this.position.add(this.velocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkBoundaryCollision() {
|
|
||||||
if (this.position.x > width - this.r) {
|
|
||||||
this.position.x = width - this.r;
|
|
||||||
this.velocity.x *= -1;
|
|
||||||
} else if (this.position.x < this.r) {
|
|
||||||
this.position.x = this.r;
|
|
||||||
this.velocity.x *= -1;
|
|
||||||
} else if (this.position.y > height - this.r) {
|
|
||||||
this.position.y = height - this.r;
|
|
||||||
this.velocity.y *= -1;
|
|
||||||
} else if (this.position.y < this.r) {
|
|
||||||
this.position.y = this.r;
|
|
||||||
this.velocity.y *= -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkCollision(other) {
|
|
||||||
// Get distances between the balls components
|
|
||||||
let distanceVect = p5.Vector.sub(other.position, this.position);
|
|
||||||
|
|
||||||
// Calculate magnitude of the vector separating the balls
|
|
||||||
let distanceVectMag = distanceVect.mag();
|
|
||||||
|
|
||||||
// Minimum distance before they are touching
|
|
||||||
let minDistance = this.r + other.r;
|
|
||||||
|
|
||||||
if (distanceVectMag < minDistance) {
|
|
||||||
let distanceCorrection = (minDistance - distanceVectMag) / 2.0;
|
|
||||||
let d = distanceVect.copy();
|
|
||||||
let correctionVector = d.normalize().mult(distanceCorrection);
|
|
||||||
other.position.add(correctionVector);
|
|
||||||
this.position.sub(correctionVector);
|
|
||||||
|
|
||||||
// get angle of distanceVect
|
|
||||||
let theta = distanceVect.heading();
|
|
||||||
// precalculate trig values
|
|
||||||
let sine = sin(theta);
|
|
||||||
let cosine = cos(theta);
|
|
||||||
|
|
||||||
/* bTemp will hold rotated ball this.positions. You
|
|
||||||
just need to worry about bTemp[1] this.position*/
|
|
||||||
let bTemp = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
/* this ball's this.position is relative to the other
|
|
||||||
so you can use the vector between them (bVect) as the
|
|
||||||
reference point in the rotation expressions.
|
|
||||||
bTemp[0].this.position.x and bTemp[0].this.position.y will initialize
|
|
||||||
automatically to 0.0, which is what you want
|
|
||||||
since b[1] will rotate around b[0] */
|
|
||||||
bTemp[1].x = cosine * distanceVect.x + sine * distanceVect.y;
|
|
||||||
bTemp[1].y = cosine * distanceVect.y - sine * distanceVect.x;
|
|
||||||
|
|
||||||
// rotate Temporary velocities
|
|
||||||
let vTemp = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
vTemp[0].x = cosine * this.velocity.x + sine * this.velocity.y;
|
|
||||||
vTemp[0].y = cosine * this.velocity.y - sine * this.velocity.x;
|
|
||||||
vTemp[1].x = cosine * other.velocity.x + sine * other.velocity.y;
|
|
||||||
vTemp[1].y = cosine * other.velocity.y - sine * other.velocity.x;
|
|
||||||
|
|
||||||
/* Now that velocities are rotated, you can use 1D
|
|
||||||
conservation of momentum equations to calculate
|
|
||||||
the final this.velocity along the x-axis. */
|
|
||||||
let vFinal = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
// final rotated this.velocity for b[0]
|
|
||||||
vFinal[0].x =
|
|
||||||
((this.m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) /
|
|
||||||
(this.m + other.m);
|
|
||||||
vFinal[0].y = vTemp[0].y;
|
|
||||||
|
|
||||||
// final rotated this.velocity for b[0]
|
|
||||||
vFinal[1].x =
|
|
||||||
((other.m - this.m) * vTemp[1].x + 2 * this.m * vTemp[0].x) /
|
|
||||||
(this.m + other.m);
|
|
||||||
vFinal[1].y = vTemp[1].y;
|
|
||||||
|
|
||||||
// hack to avoid clumping
|
|
||||||
bTemp[0].x += vFinal[0].x;
|
|
||||||
bTemp[1].x += vFinal[1].x;
|
|
||||||
|
|
||||||
/* Rotate ball this.positions and velocities back
|
|
||||||
Reverse signs in trig expressions to rotate
|
|
||||||
in the opposite direction */
|
|
||||||
// rotate balls
|
|
||||||
let bFinal = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
|
|
||||||
bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
|
|
||||||
bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
|
|
||||||
bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;
|
|
||||||
|
|
||||||
// update balls to screen this.position
|
|
||||||
other.position.x = this.position.x + bFinal[1].x;
|
|
||||||
other.position.y = this.position.y + bFinal[1].y;
|
|
||||||
|
|
||||||
this.position.add(bFinal[0]);
|
|
||||||
|
|
||||||
// update velocities
|
|
||||||
this.velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y;
|
|
||||||
this.velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x;
|
|
||||||
other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y;
|
|
||||||
other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
display(friend1, friend2) {
|
|
||||||
this.update()
|
|
||||||
noStroke();
|
|
||||||
fill('#ff0000');
|
|
||||||
ellipse(this.position.x, this.position.y, this.r * 2, this.r * 2);
|
|
||||||
this.checkBoundaryCollision()
|
|
||||||
this.checkCollision(friend1)
|
|
||||||
this.checkCollision(friend2)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Logo {
|
|
||||||
constructor() {
|
|
||||||
this.yOffset = 0
|
|
||||||
this.up = false
|
|
||||||
this.textSize = 36
|
|
||||||
this.bounceDepth = 10
|
|
||||||
this.speed = 0.2
|
|
||||||
}
|
|
||||||
|
|
||||||
display() {
|
|
||||||
fill('#20d582');
|
|
||||||
textFont(myFont);
|
|
||||||
|
|
||||||
if (windowWidth/6 > 120) {
|
|
||||||
textSize(120);
|
|
||||||
} else {
|
|
||||||
textSize(windowWidth/6)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
text('shrinkin', width/2 - 120, 20 + 60 + this.yOffset);
|
|
||||||
text('-minkin', width/2 - 120, 100 + 60 + this.yOffset);
|
|
||||||
} else {
|
|
||||||
text('shrinkin', width/2 - 120, 50 + 90 + this.yOffset);
|
|
||||||
text('-minkin', width/2 - 120, 150 + 90 + this.yOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.bounce()
|
|
||||||
}
|
|
||||||
|
|
||||||
bounce() {
|
|
||||||
if (!this.up) {
|
|
||||||
if (this.yOffset <= this.bounceDepth) {
|
|
||||||
this.yOffset = this.yOffset + this.speed
|
|
||||||
}
|
|
||||||
if (this.yOffset > this.bounceDepth) {
|
|
||||||
this.up = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.yOffset > 0) {
|
|
||||||
this.yOffset = this.yOffset - this.speed
|
|
||||||
}
|
|
||||||
if (this.yOffset < 0) {
|
|
||||||
this.up = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let ball1 = new Ball(100, 400, 20)
|
|
||||||
let ball2 = new Ball(700, 400, 80)
|
|
||||||
let ball3 = new Ball(0, 200, 60)
|
|
||||||
let logo = new Logo()
|
|
||||||
|
|
||||||
|
|
||||||
function draw() {
|
|
||||||
background('#209bd0');
|
|
||||||
|
|
||||||
|
|
||||||
ball1.display(ball2, ball3)
|
|
||||||
ball2.display(ball1, ball3)
|
|
||||||
ball3.display(ball1, ball2)
|
|
||||||
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
ball2.r = 40;
|
|
||||||
ball3.r = 30;
|
|
||||||
} else {
|
|
||||||
ball2.r = 80;
|
|
||||||
ball3.r = 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
logo.display()
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,227 +0,0 @@
|
||||||
let myFont;
|
|
||||||
function preload() {
|
|
||||||
myFont = loadFont('assets/fonts/nabla.ttf');
|
|
||||||
}
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
var canvas = createCanvas(1200, 400);
|
|
||||||
canvas.parent('shrinkin-sketch')
|
|
||||||
createLoop({duration:120, gif:true})
|
|
||||||
}
|
|
||||||
|
|
||||||
function windowResized() {
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
var canvas = resizeCanvas(windowWidth, 200);
|
|
||||||
} else {
|
|
||||||
var canvas = resizeCanvas(windowWidth, 300);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Ball {
|
|
||||||
constructor(x, y, r) {
|
|
||||||
this.position = new p5.Vector(x, y);
|
|
||||||
this.velocity = p5.Vector.random2D();
|
|
||||||
this.velocity.mult(3);
|
|
||||||
this.r = r;
|
|
||||||
this.m = r * 0.1;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
update() {
|
|
||||||
this.position.add(this.velocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkBoundaryCollision() {
|
|
||||||
if (this.position.x > width - this.r) {
|
|
||||||
this.position.x = width - this.r;
|
|
||||||
this.velocity.x *= -1;
|
|
||||||
} else if (this.position.x < this.r) {
|
|
||||||
this.position.x = this.r;
|
|
||||||
this.velocity.x *= -1;
|
|
||||||
} else if (this.position.y > height - this.r) {
|
|
||||||
this.position.y = height - this.r;
|
|
||||||
this.velocity.y *= -1;
|
|
||||||
} else if (this.position.y < this.r) {
|
|
||||||
this.position.y = this.r;
|
|
||||||
this.velocity.y *= -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkCollision(other) {
|
|
||||||
// Get distances between the balls components
|
|
||||||
let distanceVect = p5.Vector.sub(other.position, this.position);
|
|
||||||
|
|
||||||
// Calculate magnitude of the vector separating the balls
|
|
||||||
let distanceVectMag = distanceVect.mag();
|
|
||||||
|
|
||||||
// Minimum distance before they are touching
|
|
||||||
let minDistance = this.r + other.r;
|
|
||||||
|
|
||||||
if (distanceVectMag < minDistance) {
|
|
||||||
let distanceCorrection = (minDistance - distanceVectMag) / 2.0;
|
|
||||||
let d = distanceVect.copy();
|
|
||||||
let correctionVector = d.normalize().mult(distanceCorrection);
|
|
||||||
other.position.add(correctionVector);
|
|
||||||
this.position.sub(correctionVector);
|
|
||||||
|
|
||||||
// get angle of distanceVect
|
|
||||||
let theta = distanceVect.heading();
|
|
||||||
// precalculate trig values
|
|
||||||
let sine = sin(theta);
|
|
||||||
let cosine = cos(theta);
|
|
||||||
|
|
||||||
/* bTemp will hold rotated ball this.positions. You
|
|
||||||
just need to worry about bTemp[1] this.position*/
|
|
||||||
let bTemp = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
/* this ball's this.position is relative to the other
|
|
||||||
so you can use the vector between them (bVect) as the
|
|
||||||
reference point in the rotation expressions.
|
|
||||||
bTemp[0].this.position.x and bTemp[0].this.position.y will initialize
|
|
||||||
automatically to 0.0, which is what you want
|
|
||||||
since b[1] will rotate around b[0] */
|
|
||||||
bTemp[1].x = cosine * distanceVect.x + sine * distanceVect.y;
|
|
||||||
bTemp[1].y = cosine * distanceVect.y - sine * distanceVect.x;
|
|
||||||
|
|
||||||
// rotate Temporary velocities
|
|
||||||
let vTemp = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
vTemp[0].x = cosine * this.velocity.x + sine * this.velocity.y;
|
|
||||||
vTemp[0].y = cosine * this.velocity.y - sine * this.velocity.x;
|
|
||||||
vTemp[1].x = cosine * other.velocity.x + sine * other.velocity.y;
|
|
||||||
vTemp[1].y = cosine * other.velocity.y - sine * other.velocity.x;
|
|
||||||
|
|
||||||
/* Now that velocities are rotated, you can use 1D
|
|
||||||
conservation of momentum equations to calculate
|
|
||||||
the final this.velocity along the x-axis. */
|
|
||||||
let vFinal = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
// final rotated this.velocity for b[0]
|
|
||||||
vFinal[0].x =
|
|
||||||
((this.m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) /
|
|
||||||
(this.m + other.m);
|
|
||||||
vFinal[0].y = vTemp[0].y;
|
|
||||||
|
|
||||||
// final rotated this.velocity for b[0]
|
|
||||||
vFinal[1].x =
|
|
||||||
((other.m - this.m) * vTemp[1].x + 2 * this.m * vTemp[0].x) /
|
|
||||||
(this.m + other.m);
|
|
||||||
vFinal[1].y = vTemp[1].y;
|
|
||||||
|
|
||||||
// hack to avoid clumping
|
|
||||||
bTemp[0].x += vFinal[0].x;
|
|
||||||
bTemp[1].x += vFinal[1].x;
|
|
||||||
|
|
||||||
/* Rotate ball this.positions and velocities back
|
|
||||||
Reverse signs in trig expressions to rotate
|
|
||||||
in the opposite direction */
|
|
||||||
// rotate balls
|
|
||||||
let bFinal = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
|
|
||||||
bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
|
|
||||||
bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
|
|
||||||
bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;
|
|
||||||
|
|
||||||
// update balls to screen this.position
|
|
||||||
other.position.x = this.position.x + bFinal[1].x;
|
|
||||||
other.position.y = this.position.y + bFinal[1].y;
|
|
||||||
|
|
||||||
this.position.add(bFinal[0]);
|
|
||||||
|
|
||||||
// update velocities
|
|
||||||
this.velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y;
|
|
||||||
this.velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x;
|
|
||||||
other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y;
|
|
||||||
other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
display(friend1, friend2) {
|
|
||||||
this.update()
|
|
||||||
noStroke();
|
|
||||||
fill('#ff0000');
|
|
||||||
ellipse(this.position.x, this.position.y, this.r * 2, this.r * 2);
|
|
||||||
this.checkBoundaryCollision()
|
|
||||||
this.checkCollision(friend1)
|
|
||||||
this.checkCollision(friend2)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Logo {
|
|
||||||
constructor() {
|
|
||||||
this.yOffset = 0
|
|
||||||
this.up = false
|
|
||||||
this.textSize = 36
|
|
||||||
this.bounceDepth = 10
|
|
||||||
this.speed = 0.2
|
|
||||||
}
|
|
||||||
|
|
||||||
display() {
|
|
||||||
fill('#20d582');
|
|
||||||
textFont(myFont);
|
|
||||||
|
|
||||||
if (windowWidth/6 > 120) {
|
|
||||||
textSize(120);
|
|
||||||
} else {
|
|
||||||
textSize(windowWidth/6)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
text('shrinkin', width/2 - 120, 20 + 60 + this.yOffset);
|
|
||||||
text('-minkin', width/2 - 120, 100 + 60 + this.yOffset);
|
|
||||||
} else {
|
|
||||||
text('shrinkin', width/2 - 120, 50 + 90 + this.yOffset);
|
|
||||||
text('-minkin', width/2 - 120, 150 + 90 + this.yOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.bounce()
|
|
||||||
}
|
|
||||||
|
|
||||||
bounce() {
|
|
||||||
if (!this.up) {
|
|
||||||
if (this.yOffset <= this.bounceDepth) {
|
|
||||||
this.yOffset = this.yOffset + this.speed
|
|
||||||
}
|
|
||||||
if (this.yOffset > this.bounceDepth) {
|
|
||||||
this.up = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.yOffset > 0) {
|
|
||||||
this.yOffset = this.yOffset - this.speed
|
|
||||||
}
|
|
||||||
if (this.yOffset < 0) {
|
|
||||||
this.up = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let ball1 = new Ball(100, 400, 20)
|
|
||||||
let ball2 = new Ball(700, 400, 80)
|
|
||||||
let ball3 = new Ball(0, 200, 60)
|
|
||||||
let logo = new Logo()
|
|
||||||
|
|
||||||
|
|
||||||
function draw() {
|
|
||||||
background('#209bd0');
|
|
||||||
|
|
||||||
|
|
||||||
ball1.display(ball2, ball3)
|
|
||||||
ball2.display(ball1, ball3)
|
|
||||||
ball3.display(ball1, ball2)
|
|
||||||
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
ball2.r = 40;
|
|
||||||
ball3.r = 30;
|
|
||||||
} else {
|
|
||||||
ball2.r = 80;
|
|
||||||
ball3.r = 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
logo.display()
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
from django.contrib import admin
|
|
||||||
from web.models import MailingList
|
|
||||||
|
|
||||||
admin.site.register(MailingList)
|
|
||||||
|
|
||||||
# Register your models here.
|
|
|
@ -1,6 +0,0 @@
|
||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class WebConfig(AppConfig):
|
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
|
||||||
name = 'web'
|
|
|
@ -1,27 +0,0 @@
|
||||||
# Generated by Django 5.2.3 on 2025-06-29 21:28
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='MailingList',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True, null=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True, null=True)),
|
|
||||||
('active', models.BooleanField(default=True)),
|
|
||||||
('email', models.EmailField(max_length=254)),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'abstract': False,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,14 +0,0 @@
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class BaseModel(models.Model):
|
|
||||||
created_at = models.DateTimeField(blank=True, null=True, auto_now_add=True)
|
|
||||||
updated_at = models.DateTimeField(blank=True, null=True, auto_now=True)
|
|
||||||
active = models.BooleanField(default=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
|
|
||||||
class MailingList(BaseModel):
|
|
||||||
email = models.EmailField(max_length=254, blank=False, null=False)
|
|
7
web/static/css/bootstrap.min.css
vendored
|
@ -1,69 +0,0 @@
|
||||||
@font-face { font-family: Virgo; src: url('../fonts/virgo.ttf'); }
|
|
||||||
|
|
||||||
body {
|
|
||||||
background-color: #189ccf;
|
|
||||||
font-family: Virgo, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-img {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 600px;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
|
||||||
margin-top: 20px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link {
|
|
||||||
width: 150px;
|
|
||||||
padding-right: 10px;
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 45px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#band-img-1 {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iframe-container {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
width: 100%;
|
|
||||||
padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */
|
|
||||||
}
|
|
||||||
|
|
||||||
.responsive-iframe {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navi-link {
|
|
||||||
color: #ff0000;
|
|
||||||
padding-left: 10px;
|
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navi-link:hover {
|
|
||||||
opacity: 70%;
|
|
||||||
color: #ff0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-container {
|
|
||||||
color: #20d582;
|
|
||||||
background-color: #8220d5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-image {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 145 KiB |
Before Width: | Height: | Size: 242 KiB |
Before Width: | Height: | Size: 5.7 MiB |
Before Width: | Height: | Size: 47 KiB |
7
web/static/js/bootstrap.min.js
vendored
2
web/static/js/p5.min.js
vendored
|
@ -1,230 +0,0 @@
|
||||||
let myFont;
|
|
||||||
function preload() {
|
|
||||||
myFont = loadFont('assets/fonts/nabla.ttf');
|
|
||||||
}
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
var canvas = createCanvas(windowWidth, 200);
|
|
||||||
} else {
|
|
||||||
var canvas = createCanvas(windowWidth, 300);
|
|
||||||
}
|
|
||||||
canvas.parent('shrinkin-sketch')
|
|
||||||
}
|
|
||||||
|
|
||||||
function windowResized() {
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
var canvas = resizeCanvas(windowWidth, 200);
|
|
||||||
} else {
|
|
||||||
var canvas = resizeCanvas(windowWidth, 300);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Ball {
|
|
||||||
constructor(x, y, r) {
|
|
||||||
this.position = new p5.Vector(x, y);
|
|
||||||
this.velocity = p5.Vector.random2D();
|
|
||||||
this.velocity.mult(3);
|
|
||||||
this.r = r;
|
|
||||||
this.m = r * 0.1;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
update() {
|
|
||||||
this.position.add(this.velocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkBoundaryCollision() {
|
|
||||||
if (this.position.x > width - this.r) {
|
|
||||||
this.position.x = width - this.r;
|
|
||||||
this.velocity.x *= -1;
|
|
||||||
} else if (this.position.x < this.r) {
|
|
||||||
this.position.x = this.r;
|
|
||||||
this.velocity.x *= -1;
|
|
||||||
} else if (this.position.y > height - this.r) {
|
|
||||||
this.position.y = height - this.r;
|
|
||||||
this.velocity.y *= -1;
|
|
||||||
} else if (this.position.y < this.r) {
|
|
||||||
this.position.y = this.r;
|
|
||||||
this.velocity.y *= -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkCollision(other) {
|
|
||||||
// Get distances between the balls components
|
|
||||||
let distanceVect = p5.Vector.sub(other.position, this.position);
|
|
||||||
|
|
||||||
// Calculate magnitude of the vector separating the balls
|
|
||||||
let distanceVectMag = distanceVect.mag();
|
|
||||||
|
|
||||||
// Minimum distance before they are touching
|
|
||||||
let minDistance = this.r + other.r;
|
|
||||||
|
|
||||||
if (distanceVectMag < minDistance) {
|
|
||||||
let distanceCorrection = (minDistance - distanceVectMag) / 2.0;
|
|
||||||
let d = distanceVect.copy();
|
|
||||||
let correctionVector = d.normalize().mult(distanceCorrection);
|
|
||||||
other.position.add(correctionVector);
|
|
||||||
this.position.sub(correctionVector);
|
|
||||||
|
|
||||||
// get angle of distanceVect
|
|
||||||
let theta = distanceVect.heading();
|
|
||||||
// precalculate trig values
|
|
||||||
let sine = sin(theta);
|
|
||||||
let cosine = cos(theta);
|
|
||||||
|
|
||||||
/* bTemp will hold rotated ball this.positions. You
|
|
||||||
just need to worry about bTemp[1] this.position*/
|
|
||||||
let bTemp = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
/* this ball's this.position is relative to the other
|
|
||||||
so you can use the vector between them (bVect) as the
|
|
||||||
reference point in the rotation expressions.
|
|
||||||
bTemp[0].this.position.x and bTemp[0].this.position.y will initialize
|
|
||||||
automatically to 0.0, which is what you want
|
|
||||||
since b[1] will rotate around b[0] */
|
|
||||||
bTemp[1].x = cosine * distanceVect.x + sine * distanceVect.y;
|
|
||||||
bTemp[1].y = cosine * distanceVect.y - sine * distanceVect.x;
|
|
||||||
|
|
||||||
// rotate Temporary velocities
|
|
||||||
let vTemp = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
vTemp[0].x = cosine * this.velocity.x + sine * this.velocity.y;
|
|
||||||
vTemp[0].y = cosine * this.velocity.y - sine * this.velocity.x;
|
|
||||||
vTemp[1].x = cosine * other.velocity.x + sine * other.velocity.y;
|
|
||||||
vTemp[1].y = cosine * other.velocity.y - sine * other.velocity.x;
|
|
||||||
|
|
||||||
/* Now that velocities are rotated, you can use 1D
|
|
||||||
conservation of momentum equations to calculate
|
|
||||||
the final this.velocity along the x-axis. */
|
|
||||||
let vFinal = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
// final rotated this.velocity for b[0]
|
|
||||||
vFinal[0].x =
|
|
||||||
((this.m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) /
|
|
||||||
(this.m + other.m);
|
|
||||||
vFinal[0].y = vTemp[0].y;
|
|
||||||
|
|
||||||
// final rotated this.velocity for b[0]
|
|
||||||
vFinal[1].x =
|
|
||||||
((other.m - this.m) * vTemp[1].x + 2 * this.m * vTemp[0].x) /
|
|
||||||
(this.m + other.m);
|
|
||||||
vFinal[1].y = vTemp[1].y;
|
|
||||||
|
|
||||||
// hack to avoid clumping
|
|
||||||
bTemp[0].x += vFinal[0].x;
|
|
||||||
bTemp[1].x += vFinal[1].x;
|
|
||||||
|
|
||||||
/* Rotate ball this.positions and velocities back
|
|
||||||
Reverse signs in trig expressions to rotate
|
|
||||||
in the opposite direction */
|
|
||||||
// rotate balls
|
|
||||||
let bFinal = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
|
|
||||||
bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
|
|
||||||
bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
|
|
||||||
bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;
|
|
||||||
|
|
||||||
// update balls to screen this.position
|
|
||||||
other.position.x = this.position.x + bFinal[1].x;
|
|
||||||
other.position.y = this.position.y + bFinal[1].y;
|
|
||||||
|
|
||||||
this.position.add(bFinal[0]);
|
|
||||||
|
|
||||||
// update velocities
|
|
||||||
this.velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y;
|
|
||||||
this.velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x;
|
|
||||||
other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y;
|
|
||||||
other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
display(friend1, friend2) {
|
|
||||||
this.update()
|
|
||||||
noStroke();
|
|
||||||
fill('#ff0000');
|
|
||||||
ellipse(this.position.x, this.position.y, this.r * 2, this.r * 2);
|
|
||||||
this.checkBoundaryCollision()
|
|
||||||
this.checkCollision(friend1)
|
|
||||||
this.checkCollision(friend2)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Logo {
|
|
||||||
constructor() {
|
|
||||||
this.yOffset = 0
|
|
||||||
this.up = false
|
|
||||||
this.textSize = 36
|
|
||||||
this.bounceDepth = 10
|
|
||||||
this.speed = 0.2
|
|
||||||
}
|
|
||||||
|
|
||||||
display() {
|
|
||||||
fill('#20d582');
|
|
||||||
textFont(myFont);
|
|
||||||
|
|
||||||
if (windowWidth/6 > 120) {
|
|
||||||
textSize(120);
|
|
||||||
} else {
|
|
||||||
textSize(windowWidth/6)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
text('shrinkin', width/2 - 120, 20 + 60 + this.yOffset);
|
|
||||||
text('-minkin', width/2 - 120, 100 + 60 + this.yOffset);
|
|
||||||
} else {
|
|
||||||
text('shrinkin', width/2 - 120, 50 + 90 + this.yOffset);
|
|
||||||
text('-minkin', width/2 - 120, 150 + 90 + this.yOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.bounce()
|
|
||||||
}
|
|
||||||
|
|
||||||
bounce() {
|
|
||||||
if (!this.up) {
|
|
||||||
if (this.yOffset <= this.bounceDepth) {
|
|
||||||
this.yOffset = this.yOffset + this.speed
|
|
||||||
}
|
|
||||||
if (this.yOffset > this.bounceDepth) {
|
|
||||||
this.up = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.yOffset > 0) {
|
|
||||||
this.yOffset = this.yOffset - this.speed
|
|
||||||
}
|
|
||||||
if (this.yOffset < 0) {
|
|
||||||
this.up = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let ball1 = new Ball(100, 400, 20)
|
|
||||||
let ball2 = new Ball(700, 400, 80)
|
|
||||||
let ball3 = new Ball(0, 200, 60)
|
|
||||||
let logo = new Logo()
|
|
||||||
|
|
||||||
|
|
||||||
function draw() {
|
|
||||||
background('#209bd0');
|
|
||||||
|
|
||||||
|
|
||||||
ball1.display(ball2, ball3)
|
|
||||||
ball2.display(ball1, ball3)
|
|
||||||
ball3.display(ball1, ball2)
|
|
||||||
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
ball2.r = 40;
|
|
||||||
ball3.r = 30;
|
|
||||||
} else {
|
|
||||||
ball2.r = 80;
|
|
||||||
ball3.r = 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
logo.display()
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,227 +0,0 @@
|
||||||
let myFont;
|
|
||||||
function preload() {
|
|
||||||
myFont = loadFont('assets/fonts/nabla.ttf');
|
|
||||||
}
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
var canvas = createCanvas(1200, 400);
|
|
||||||
canvas.parent('shrinkin-sketch')
|
|
||||||
createLoop({duration:120, gif:true})
|
|
||||||
}
|
|
||||||
|
|
||||||
function windowResized() {
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
var canvas = resizeCanvas(windowWidth, 200);
|
|
||||||
} else {
|
|
||||||
var canvas = resizeCanvas(windowWidth, 300);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Ball {
|
|
||||||
constructor(x, y, r) {
|
|
||||||
this.position = new p5.Vector(x, y);
|
|
||||||
this.velocity = p5.Vector.random2D();
|
|
||||||
this.velocity.mult(3);
|
|
||||||
this.r = r;
|
|
||||||
this.m = r * 0.1;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
update() {
|
|
||||||
this.position.add(this.velocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkBoundaryCollision() {
|
|
||||||
if (this.position.x > width - this.r) {
|
|
||||||
this.position.x = width - this.r;
|
|
||||||
this.velocity.x *= -1;
|
|
||||||
} else if (this.position.x < this.r) {
|
|
||||||
this.position.x = this.r;
|
|
||||||
this.velocity.x *= -1;
|
|
||||||
} else if (this.position.y > height - this.r) {
|
|
||||||
this.position.y = height - this.r;
|
|
||||||
this.velocity.y *= -1;
|
|
||||||
} else if (this.position.y < this.r) {
|
|
||||||
this.position.y = this.r;
|
|
||||||
this.velocity.y *= -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkCollision(other) {
|
|
||||||
// Get distances between the balls components
|
|
||||||
let distanceVect = p5.Vector.sub(other.position, this.position);
|
|
||||||
|
|
||||||
// Calculate magnitude of the vector separating the balls
|
|
||||||
let distanceVectMag = distanceVect.mag();
|
|
||||||
|
|
||||||
// Minimum distance before they are touching
|
|
||||||
let minDistance = this.r + other.r;
|
|
||||||
|
|
||||||
if (distanceVectMag < minDistance) {
|
|
||||||
let distanceCorrection = (minDistance - distanceVectMag) / 2.0;
|
|
||||||
let d = distanceVect.copy();
|
|
||||||
let correctionVector = d.normalize().mult(distanceCorrection);
|
|
||||||
other.position.add(correctionVector);
|
|
||||||
this.position.sub(correctionVector);
|
|
||||||
|
|
||||||
// get angle of distanceVect
|
|
||||||
let theta = distanceVect.heading();
|
|
||||||
// precalculate trig values
|
|
||||||
let sine = sin(theta);
|
|
||||||
let cosine = cos(theta);
|
|
||||||
|
|
||||||
/* bTemp will hold rotated ball this.positions. You
|
|
||||||
just need to worry about bTemp[1] this.position*/
|
|
||||||
let bTemp = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
/* this ball's this.position is relative to the other
|
|
||||||
so you can use the vector between them (bVect) as the
|
|
||||||
reference point in the rotation expressions.
|
|
||||||
bTemp[0].this.position.x and bTemp[0].this.position.y will initialize
|
|
||||||
automatically to 0.0, which is what you want
|
|
||||||
since b[1] will rotate around b[0] */
|
|
||||||
bTemp[1].x = cosine * distanceVect.x + sine * distanceVect.y;
|
|
||||||
bTemp[1].y = cosine * distanceVect.y - sine * distanceVect.x;
|
|
||||||
|
|
||||||
// rotate Temporary velocities
|
|
||||||
let vTemp = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
vTemp[0].x = cosine * this.velocity.x + sine * this.velocity.y;
|
|
||||||
vTemp[0].y = cosine * this.velocity.y - sine * this.velocity.x;
|
|
||||||
vTemp[1].x = cosine * other.velocity.x + sine * other.velocity.y;
|
|
||||||
vTemp[1].y = cosine * other.velocity.y - sine * other.velocity.x;
|
|
||||||
|
|
||||||
/* Now that velocities are rotated, you can use 1D
|
|
||||||
conservation of momentum equations to calculate
|
|
||||||
the final this.velocity along the x-axis. */
|
|
||||||
let vFinal = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
// final rotated this.velocity for b[0]
|
|
||||||
vFinal[0].x =
|
|
||||||
((this.m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) /
|
|
||||||
(this.m + other.m);
|
|
||||||
vFinal[0].y = vTemp[0].y;
|
|
||||||
|
|
||||||
// final rotated this.velocity for b[0]
|
|
||||||
vFinal[1].x =
|
|
||||||
((other.m - this.m) * vTemp[1].x + 2 * this.m * vTemp[0].x) /
|
|
||||||
(this.m + other.m);
|
|
||||||
vFinal[1].y = vTemp[1].y;
|
|
||||||
|
|
||||||
// hack to avoid clumping
|
|
||||||
bTemp[0].x += vFinal[0].x;
|
|
||||||
bTemp[1].x += vFinal[1].x;
|
|
||||||
|
|
||||||
/* Rotate ball this.positions and velocities back
|
|
||||||
Reverse signs in trig expressions to rotate
|
|
||||||
in the opposite direction */
|
|
||||||
// rotate balls
|
|
||||||
let bFinal = [new p5.Vector(), new p5.Vector()];
|
|
||||||
|
|
||||||
bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
|
|
||||||
bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
|
|
||||||
bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
|
|
||||||
bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;
|
|
||||||
|
|
||||||
// update balls to screen this.position
|
|
||||||
other.position.x = this.position.x + bFinal[1].x;
|
|
||||||
other.position.y = this.position.y + bFinal[1].y;
|
|
||||||
|
|
||||||
this.position.add(bFinal[0]);
|
|
||||||
|
|
||||||
// update velocities
|
|
||||||
this.velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y;
|
|
||||||
this.velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x;
|
|
||||||
other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y;
|
|
||||||
other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
display(friend1, friend2) {
|
|
||||||
this.update()
|
|
||||||
noStroke();
|
|
||||||
fill('#ff0000');
|
|
||||||
ellipse(this.position.x, this.position.y, this.r * 2, this.r * 2);
|
|
||||||
this.checkBoundaryCollision()
|
|
||||||
this.checkCollision(friend1)
|
|
||||||
this.checkCollision(friend2)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Logo {
|
|
||||||
constructor() {
|
|
||||||
this.yOffset = 0
|
|
||||||
this.up = false
|
|
||||||
this.textSize = 36
|
|
||||||
this.bounceDepth = 10
|
|
||||||
this.speed = 0.2
|
|
||||||
}
|
|
||||||
|
|
||||||
display() {
|
|
||||||
fill('#20d582');
|
|
||||||
textFont(myFont);
|
|
||||||
|
|
||||||
if (windowWidth/6 > 120) {
|
|
||||||
textSize(120);
|
|
||||||
} else {
|
|
||||||
textSize(windowWidth/6)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
text('shrinkin', width/2 - 120, 20 + 60 + this.yOffset);
|
|
||||||
text('-minkin', width/2 - 120, 100 + 60 + this.yOffset);
|
|
||||||
} else {
|
|
||||||
text('shrinkin', width/2 - 120, 50 + 90 + this.yOffset);
|
|
||||||
text('-minkin', width/2 - 120, 150 + 90 + this.yOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.bounce()
|
|
||||||
}
|
|
||||||
|
|
||||||
bounce() {
|
|
||||||
if (!this.up) {
|
|
||||||
if (this.yOffset <= this.bounceDepth) {
|
|
||||||
this.yOffset = this.yOffset + this.speed
|
|
||||||
}
|
|
||||||
if (this.yOffset > this.bounceDepth) {
|
|
||||||
this.up = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.yOffset > 0) {
|
|
||||||
this.yOffset = this.yOffset - this.speed
|
|
||||||
}
|
|
||||||
if (this.yOffset < 0) {
|
|
||||||
this.up = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let ball1 = new Ball(100, 400, 20)
|
|
||||||
let ball2 = new Ball(700, 400, 80)
|
|
||||||
let ball3 = new Ball(0, 200, 60)
|
|
||||||
let logo = new Logo()
|
|
||||||
|
|
||||||
|
|
||||||
function draw() {
|
|
||||||
background('#209bd0');
|
|
||||||
|
|
||||||
|
|
||||||
ball1.display(ball2, ball3)
|
|
||||||
ball2.display(ball1, ball3)
|
|
||||||
ball3.display(ball1, ball2)
|
|
||||||
|
|
||||||
if (windowWidth <= 480) {
|
|
||||||
ball2.r = 40;
|
|
||||||
ball3.r = 30;
|
|
||||||
} else {
|
|
||||||
ball2.r = 80;
|
|
||||||
ball3.r = 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
logo.display()
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
{% load static %}
|
|
||||||
{% block 'content' %}
|
|
||||||
<div class="container">
|
|
||||||
<center>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
<h5>Listen to our first album Tyrannizing Harmonics Everywhere!!</h5>
|
|
||||||
<br>
|
|
||||||
<div style="margin: 0 auto; max-width: 600px;">
|
|
||||||
<iframe style="border: 0; width: 100%; height: 439px;" src="https://bandcamp.com/EmbeddedPlayer/album=4037494074/size=large/bgcol=ffffff/linkcol=0687f5/artwork=small/transparent=true/" seamless><a href="https://shrinkin-minkin.bandcamp.com/album/tyrannizing-harmonics">Tyrannizing Harmonics by shrinkin-minkin</a></iframe>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a target="_blank" href="https://open.spotify.com/album/4imchLIIQnfFfrxcy0bQ3l">
|
|
||||||
<button type="button" class="btn btn-light link">Spotify</button><br>
|
|
||||||
</a>
|
|
||||||
<a target="_blank" href="https://shrinkin-minkin.bandcamp.com/album/tyrannizing-harmonics">
|
|
||||||
<button type="button" class="btn btn-light link">Bandcamp</button><br>
|
|
||||||
</a>
|
|
||||||
<a target="_blank" href="https://www.youtube.com/watch?v=hwaWr7GQ09M&list=OLAK5uy_mr2CAlUomJZIEd3Y0_vIiguRz80bXNmwI">
|
|
||||||
<button type="button" class="btn btn-light link">YouTube</button><br>
|
|
||||||
</a>
|
|
||||||
<a target="_blank" href="https://music.apple.com/us/album/tyrannizing-harmonics/1814317803" style="display:none;">
|
|
||||||
<button type="button" class="btn btn-light link">Apple Music</button><br>
|
|
||||||
</a>
|
|
||||||
<a target="_blank" href="https://www.pandora.com/artist/shrinkin-minkin/tyrannizing-harmonics/AL3j4zhrhJbf4cP">
|
|
||||||
<button type="button" class="btn btn-light link">Pandora</button><br>
|
|
||||||
</a>
|
|
||||||
<a target="_blank" href="https://www.instagram.com/shrinkinminkin/">
|
|
||||||
<button type="button" class="btn btn-light link">Follow us on Instagram</button><br>
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
{% include 'mailing_list.html' %}
|
|
||||||
|
|
||||||
|
|
||||||
We hope you enjoy our ad free listening experience! Please visit our socials and like and subscribe to support us!
|
|
||||||
</center>
|
|
||||||
<br><br>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
|
@ -1,45 +0,0 @@
|
||||||
{% load static %}
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Shrinkin-Minkin</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
|
|
||||||
<link rel="stylesheet" href="{% static 'css/style.css' %}">
|
|
||||||
</head>
|
|
||||||
<body style="padding: 0px; margin: 0px;">
|
|
||||||
{% if messages %}
|
|
||||||
{% for message in messages %}
|
|
||||||
<div class="alert alert-success alert-dismissible fade show"
|
|
||||||
role="alert"
|
|
||||||
style="max-width:400px;
|
|
||||||
position: fixed;
|
|
||||||
bottom:0;
|
|
||||||
right: 0;
|
|
||||||
margin:20px">
|
|
||||||
{{ message }}
|
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
||||||
<span aria-hidden="true">X</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
<center>
|
|
||||||
<a href="{% url 'index' %}">
|
|
||||||
<img src="{% static 'img/album_release_header.png' %}"
|
|
||||||
alt=""
|
|
||||||
class="header-img">
|
|
||||||
<br>
|
|
||||||
</a>
|
|
||||||
</center>
|
|
||||||
{% block 'content' %}{% endblock %}
|
|
||||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
|
|
||||||
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js"
|
|
||||||
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js"
|
|
||||||
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
</body>
|
|
|
@ -1,123 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
{% load static %}
|
|
||||||
{% block 'content' %}
|
|
||||||
<div>
|
|
||||||
<center>
|
|
||||||
<a href="#listen">
|
|
||||||
<button type="button" class="btn btn-light nav-link">listen</button>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#watch">
|
|
||||||
<button type="button" class="btn btn-light nav-link">watch</button>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#book">
|
|
||||||
<button type="button" class="btn btn-light nav-link">book us</button>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="{% url 'socials' %}">
|
|
||||||
<button type="button" class="btn btn-light nav-link">social</button>
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
</center>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container-fluid pt-2 mt-3">
|
|
||||||
|
|
||||||
<div class="row pb-4">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<center>
|
|
||||||
<img id="band-img-1" class="img-fluid" src="{% static 'img/members.png' %}" alt="" style="margin-bottom: 20px; width:100%; height: auto; max-width: 840px;">
|
|
||||||
|
|
||||||
<div style="margin-top:30px; margin-bottom: 20px;">
|
|
||||||
{% include 'mailing_list.html' %}
|
|
||||||
</div>
|
|
||||||
</center>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-6" style="padding:30px; background-color: #54b879;">
|
|
||||||
<h1>About Us:</h1>
|
|
||||||
<p>
|
|
||||||
<b>SHRINKIN-MINKIN</b> thrives on the fringes of genre, violating the confines of classification.
|
|
||||||
Founded in 2022 by singer/guitarists Dominic DiTaranto and Michael Heinfling;
|
|
||||||
SHRINKIN-MINKIN blends Rock, Funk, Jazz, Punk, infused with creative improvisation and FX landscape.
|
|
||||||
The NJ based 5-piece is <i>tight</i>. Technical, Playful, and dripping with thirst-quenching satire.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Their musical multiplicity allows SHRINKIN-MINKIN to fit into any lineup.
|
|
||||||
Their songs range from the Funk, Rock, Hip Hop, Gospel fusion of "GLOP";
|
|
||||||
to Post-Punk anthems like "Industry Rock" and the comical love-lament of "Butter Queen".
|
|
||||||
Songs that are guaranteed to get asses convulsing in rhythmic fervor.
|
|
||||||
More discerning listeners can relax and watch the band trade solos on "Down Polypore Wood".
|
|
||||||
Add in Alternative ballads, Blues tracks, and even a Psychedelic-Waltz and you will begin to scratch
|
|
||||||
the surface of what SHRINKIN-MINKIN has to offer.
|
|
||||||
<br><br>
|
|
||||||
<a href="#book">Book Us</a> now to support or headline!
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<b>Members:</b>
|
|
||||||
<br>Dominic DiTaranto - Guitar/Vocals/Synth
|
|
||||||
<br>Michael Heinfling - Guitar/Vocals
|
|
||||||
<br>Charlie Misch - Keyboard/Synth
|
|
||||||
<br>B.S. Ashford - Bass
|
|
||||||
<br>Recon Paul - Drums
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<b>Recommended if you like:</b>
|
|
||||||
Frank Zappa,
|
|
||||||
King Crimson,
|
|
||||||
Talking Heads,
|
|
||||||
David Bowie,
|
|
||||||
Mahavishnu Orchestra,
|
|
||||||
Phish,
|
|
||||||
Miles Davis,
|
|
||||||
The Stooges,
|
|
||||||
Funkadelic,
|
|
||||||
John Coltrane,
|
|
||||||
The Stranglers,
|
|
||||||
The Damned,
|
|
||||||
Weather Report,
|
|
||||||
The Cars
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1 id="listen">Listen:</h1>
|
|
||||||
<center>
|
|
||||||
<iframe style="border: 0; max-width: 350px; height: 753px;" src="https://bandcamp.com/EmbeddedPlayer/album=4037494074/size=large/bgcol=ffffff/linkcol=de270f/transparent=true/" seamless><a href="https://shrinkin-minkin.bandcamp.com/album/tyrannizing-harmonics">Tyrannizing Harmonics by shrinkin-minkin</a></iframe>
|
|
||||||
</center>
|
|
||||||
<br><br>
|
|
||||||
|
|
||||||
<h1 id="watch">Watch Us Live:</h1>
|
|
||||||
<div class="iframe-container">
|
|
||||||
|
|
||||||
<iframe class="responsive-iframe" src="https://www.youtube.com/embed/7Dbg5MuOgbY?si=qW3dw8QY4a8sHqbX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
|
||||||
</div>
|
|
||||||
<br><br>
|
|
||||||
<div class="iframe-container">
|
|
||||||
<iframe class="responsive-iframe" src="https://www.youtube.com/embed/4Cx1_LMJRzM?si=fS9EuyczsNvsJuSb&start=42" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
|
||||||
</div>
|
|
||||||
<br><br>
|
|
||||||
<div class="iframe-container">
|
|
||||||
<iframe class="responsive-iframe" src="https://www.youtube.com/embed/R3fo-k2_wfM?si=Foz0OaTK6GC5psKo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-5 mb-5 p-5">
|
|
||||||
<h1 id="book">Book Us:</h1>
|
|
||||||
<br>
|
|
||||||
Email: shrinkinminkin<span style="font-family: monospace;">@</span>gmail.com <br>
|
|
||||||
Phone: 732-895-5253
|
|
||||||
<br><br>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<img class="footer-image" src="{% static 'img/bugman_sticker.png' %}" alt="">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
|
@ -1,8 +0,0 @@
|
||||||
<div class="card p-2" style="margin-bottom:10px;">
|
|
||||||
<form action="/mailing_list/" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
<label for="email">Join Our Mailing List:</label>
|
|
||||||
<input type="email" id="email" name="email" placeholder="your@email.com" style="font-family: monospace;">
|
|
||||||
<input type="submit" class="btn btn-success" value="JOIN">
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,44 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
{% load static %}
|
|
||||||
{% block 'content' %}
|
|
||||||
<div class="container">
|
|
||||||
<center>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
<iframe style="border: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 42px"
|
|
||||||
src="https://bandcamp.com/EmbeddedPlayer/album=4037494074/size=small/bgcol=ffffff/linkcol=0687f5/transparent=true/"
|
|
||||||
seamless><a href="https://shrinkin-minkin.bandcamp.com/album/tyrannizing-harmonics">Tyrannizing Harmonics by shrinkin-minkin</a></iframe>
|
|
||||||
<a target="_blank" href="{% url 'album' %}">
|
|
||||||
<button type="button" class="btn btn-success link">Listen To Our Album!</button>
|
|
||||||
<br>
|
|
||||||
</a>
|
|
||||||
<a target="_blank" href="https://www.instagram.com/shrinkinminkin/">
|
|
||||||
<button type="button" class="btn btn-light link">Instagram</button>
|
|
||||||
<br>
|
|
||||||
</a>
|
|
||||||
<a target="_blank" href="https://shrinkin-minkin.bandcamp.com/">
|
|
||||||
style="margin-bottom:10px;" <button type="button" class="btn btn-light link">Bandcamp</button>
|
|
||||||
<br>
|
|
||||||
</a>
|
|
||||||
<a target="_blank"
|
|
||||||
href="https://www.youtube.com/channel/UCCmRKeoqtHC9G1X-yvuUG7A">
|
|
||||||
<button type="button" class="btn btn-light link">YouTube</button>
|
|
||||||
<br>
|
|
||||||
</a>
|
|
||||||
<a target="_blank" href="https://www.shrinkinminkin.com/">
|
|
||||||
<button type="button" class="btn btn-light link">For Promoters And Venues</button>
|
|
||||||
<br>
|
|
||||||
</a>
|
|
||||||
<a target="_blank" href="https://www.bonfire.com/store/shrinkin-minkin/">
|
|
||||||
<button type="button" class="btn btn-danger link">Merch</button>
|
|
||||||
<br>
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
</center>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
|
@ -1,3 +0,0 @@
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
33
web/views.py
|
@ -1,33 +0,0 @@
|
||||||
from django.contrib import messages
|
|
||||||
from django.shortcuts import render, redirect
|
|
||||||
from web.models import MailingList
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
|
||||||
return render(request, 'index.html')
|
|
||||||
|
|
||||||
|
|
||||||
def album(request):
|
|
||||||
return render(request, 'album.html')
|
|
||||||
|
|
||||||
|
|
||||||
def socials(request):
|
|
||||||
return render(request, 'socials.html')
|
|
||||||
|
|
||||||
|
|
||||||
def mailing_list(request):
|
|
||||||
if request.method == 'POST':
|
|
||||||
referer = request.META['HTTP_REFERER'][:-1].split('/')[-1].split('.')[0]
|
|
||||||
email = request.POST.get('email')
|
|
||||||
|
|
||||||
if email:
|
|
||||||
exists = MailingList.objects.filter(email=email).first()
|
|
||||||
if not exists:
|
|
||||||
m = MailingList(
|
|
||||||
email=email
|
|
||||||
)
|
|
||||||
m.save()
|
|
||||||
messages.add_message(request, messages.INFO, "Nice! Thanks for joining our mailing list!")
|
|
||||||
|
|
||||||
return redirect(referer)
|
|