Work in progress front-end first iteration.

This commit is contained in:
Ada Werefox 2024-03-02 10:43:49 -06:00
parent df8f0b3067
commit a1e77de4b3
35 changed files with 3139 additions and 3 deletions

4
.gitignore vendored
View File

@ -1,3 +1,7 @@
**/.venv/** **/.venv/**
**/__pycache__/** **/__pycache__/**
*.pyc *.pyc
TunicTransitionTracker
settings.json
**/db.sqlite3
**/node_modules/**

19
main.py
View File

@ -4,6 +4,10 @@ import logging
from time import sleep from time import sleep
from lib import entrances as e from lib import entrances as e
from lib import saves as s from lib import saves as s
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
# Set up a default logger, later this should be changed to default only errors. # Set up a default logger, later this should be changed to default only errors.
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
@ -16,7 +20,17 @@ save = ''
# Make this an optional command based on CLI flags # Make this an optional command based on CLI flags
# e.log_entrances(entrances_map) # e.log_entrances(entrances_map)
while (True):
@app.get("/")
def homepage():
return {"Hello": "World"}
@app.get("/get/entrances")
async def get_entrances():
visited_entrances = None
save_filename = ''
save = ''
current_save_filename, current_save = s.get_current_save_filename() current_save_filename, current_save = s.get_current_save_filename()
if (current_save != save): if (current_save != save):
save = current_save save = current_save
@ -43,4 +57,5 @@ while (True):
else: else:
visited_entrances = updated_visited_entrances visited_entrances = updated_visited_entrances
logging.debug(f'Updated visited entrances to: {visited_entrances}') logging.debug(f'Updated visited entrances to: {visited_entrances}')
sleep(1)
return zip([y for x, y in enumerate(visited_entrances) if x % 2 == 0], [y for x, y in enumerate(visited_entrances) if x % 2 == 1])

View File

@ -1,21 +1,45 @@
annotated-types==0.6.0 annotated-types==0.6.0
anyio==4.3.0 anyio==4.3.0
arrow==1.3.0
asgiref==3.7.2
autopep8==2.0.4 autopep8==2.0.4
binaryornot==0.4.4
certifi==2024.2.2
chardet==5.2.0
charset-normalizer==3.3.2
click==8.1.7 click==8.1.7
cookiecutter==2.6.0
Django==5.0.2
django-browser-reload==1.12.1
django-tailwind==3.8.0
fastapi==0.110.0 fastapi==0.110.0
h11==0.14.0 h11==0.14.0
httptools==0.6.1 httptools==0.6.1
idna==3.6 idna==3.6
Jinja2==3.1.3
markdown-it-py==3.0.0
MarkupSafe==2.1.5
mdurl==0.1.2
numpy==1.26.4 numpy==1.26.4
pyarrow==15.0.0 pyarrow==15.0.0
pycodestyle==2.11.1 pycodestyle==2.11.1
pydantic==2.6.3 pydantic==2.6.3
pydantic_core==2.16.3 pydantic_core==2.16.3
Pygments==2.17.2
python-dateutil==2.8.2
python-dotenv==1.0.1 python-dotenv==1.0.1
python-slugify==8.0.4
PyYAML==6.0.1 PyYAML==6.0.1
requests==2.31.0
rich==13.7.1
six==1.16.0
sniffio==1.3.1 sniffio==1.3.1
sqlparse==0.4.4
starlette==0.36.3 starlette==0.36.3
text-unidecode==1.3
types-python-dateutil==2.8.19.20240106
typing_extensions==4.10.0 typing_extensions==4.10.0
urllib3==2.2.1
uvicorn==0.27.1 uvicorn==0.27.1
uvloop==0.19.0 uvloop==0.19.0
watchfiles==0.21.0 watchfiles==0.21.0

22
tunictracker/manage.py Executable file
View File

@ -0,0 +1,22 @@
#!/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', 'tunictracker.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()

1474
tunictracker/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

12
tunictracker/package.json Normal file
View File

@ -0,0 +1,12 @@
{
"dependencies": {
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/typography": "^0.5.10",
"cross-env": "^7.0.3"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.7",
"postcss": "^8.4.35",
"postcss-simple-vars": "^7.0.1"
}
}

View File

@ -0,0 +1,27 @@
annotated-types==0.6.0
anyio==4.3.0
asgiref==3.7.2
autopep8==2.0.4
click==8.1.7
Django==5.0.2
django-browser-reload==1.12.1
django-tailwind==3.8.0
fastapi==0.110.0
h11==0.14.0
httptools==0.6.1
idna==3.6
numpy==1.26.4
pyarrow==15.0.0
pycodestyle==2.11.1
pydantic==2.6.3
pydantic_core==2.16.3
python-dotenv==1.0.1
PyYAML==6.0.1
sniffio==1.3.1
sqlparse==0.4.4
starlette==0.36.3
typing_extensions==4.10.0
uvicorn==0.27.1
uvloop==0.19.0
watchfiles==0.21.0
websockets==12.0

View File

View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class TrackerConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'tracker'

View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>Tunic Tracker Redux</title>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8" />
{% comment %} <meta http-equiv="refresh" content="3"> {% endcomment %}
{% load static tailwind_tags %}
{% tailwind_css %}
{% load static %}
<script src="{% static 'tracker/assets/test.js' %}"></script>
</head>
<body class="bg-[#242424]">
{% block content %}
{% endblock %}
</body>
</html>

View File

@ -0,0 +1,74 @@
{% extends 'index.html' %}
{% load static %}
{% block content %}
<div class="container monospace">
<div class="m-4 pl-2 pr-2 ring-4 rounded-md text-[#eee] bg-bluelight-translucent-dark ring-bluelight-dark">
<div class="flex flex-col">
<div class="flex pt-4 text-2xl mx-2">
<span class="relative inline-block align-middle h-8 w-8"><img src="{% static 'tracker/images/neofox_flag_trans_256.png' %}" alt="A trans pride fox emoji." /></span>
&nbsp;Tunic Transition Tracker
</div>
<hr class="m-2 mb-0 border-2 border-[#2fd5ff27] rounded-md" />
<div class="flex mx-3 my-2 text-xl">
Checks: {{ totals.Checks.Undiscovered }}/{{ totals.Checks.Total }} Entrances: {{ totals.Entrances.Undiscovered }}/{{ totals.Entrances.Total }}
<br />Current Area: {{ scene }}
</div>
<div class="mx-4 mb-4 p-1 flex flex-col space-y-4">
<details open class="px-4 max-w-full rounded-md ring-4 bg-bluelight-translucent ring-[#2fd5ff10] text-[#eee]">
<summary class="justify-start p-2 text-lg">Checks: {{ scene_data.Totals.Checks.Undiscovered }}/{{ scene_data.Totals.Checks.Total }} Entrances: {{ scene_data.Totals.Entrances.Undiscovered }}/{{ scene_data.Totals.Entrances.Total }}</summary>
<hr class="mb-2 border-2 border-[#2fd5ff27] rounded-md" />
<div class="flex flex-row justify-center space-x-4">
<div class="my-2 flex flex-col basis-1/2 space-y-2 overflow-x-auto">
<div class="text-md">Checks</div>
<hr class="border-2 border-[#2fd5ff27] rounded-md" />
</div>
<div class="my-2 flex flex-col basis-1/2 space-y-2 overflow-x-auto">
<div class="text-md">Entrances</div>
<hr class="border-2 border-[#2fd5ff27] rounded-md" />
</div>
</div>
<div class="flex flex-row justify-center space-x-4">
<div class="pb-4 flex flex-col basis-1/2 space-y-2 overscroll-x-auto">
{% for check_name, check in scene_data.Checks.items %}
{% if not check.Check %}
<ul class="min-w-max bg-bluelight-translucent rounded-sm px-1">❌ {{ check_name }}</ul>
{% endif %}
{% endfor %}
</div>
<div class="pb-4 flex flex-col basis-1/2 space-y-2 overflow-x-auto">
{% for entrance_origin, entrance_destination in scene_data.Entrances.items %}
{% if not entrance_destination.Entrance != '' %}
<ul class="min-w-max bg-bluelight-translucent rounded-sm px-1">❌ {{ entrance_origin }} -> {{ entrance_destination.Entrance }}</ul>
{% endif %}
{% endfor %}
</div>
</div>
</details>
<div class="pb-4 flex flex-col space-y-2 overscroll-x-auto">
{% for entrance_origin, entrance_destination in scene_data.Entrances.items %}
{% if entrance_destination.Entrance %}
<ul class="min-w-max bg-bluelight rounded-sm px-1">✔️ {{ entrance_origin }} -> {{ entrance_destination.Entrance }}</ul>
{% endif %}
{% endfor %}
</div>
<details class="group flex max-w-full rounded-md ring-4 bg-bluelight-translucent ring-[#2fd5ff10] text-[#eee]">
<summary class="justify-start p-2">Tracker Debug</summary>
<div class="p-2 pl-4 pr-4 flex flex-col space-y-2">
<div>
<ul>Name: {{ debug.Name }}</ul>
<ul>Seed: {{ debug.Seed }}</ul>
<ul>Spoiler Seed: {{ debug.SpoilerSeed }}</ul>
<ul>Archipelago: {{ debug.Archipelago }}</ul>
<ul>Randomized: {{ debug.Randomized }}</ul>
<ul>Hex Quest: {{ debug.HexQuest }}</ul>
<ul>Entrance Randomizer: {{ debug.EntranceRando }}</ul>
<ul>Fixed Shops: {{ debug.FixedShops }}</ul>
</div>
</div>
</details>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -0,0 +1,7 @@
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
]

View File

@ -0,0 +1,42 @@
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader
from json import loads
from math import floor
import requests
# Create your views here.
def index(request):
tracker_output = loads(requests.get('http://localhost:8000/spoiler').text)
# with open('structure_final_final_v10.json', 'r') as t:
# tracker_output = loads(t.read())
tracker_debug = tracker_output["Debug"]
tracker_totals = tracker_output["Totals"]
tracker_current_scene = tracker_output["Scene"]
tracker_current_scene_data = tracker_output["Scenes"][tracker_current_scene]
template = loader.get_template("tracker/index.html")
temp_tracker_checks = tracker_current_scene_data["Checks"]
for i, check in enumerate(temp_tracker_checks.keys()):
temp_data = {
"Check": temp_tracker_checks[check],
"CheckNum": floor(int(i)%3)
}
temp_tracker_checks[check] = temp_data
tracker_current_scene_data["Checks"] = temp_tracker_checks
temp_tracker_entrances = tracker_current_scene_data["Entrances"]
for i, entrance in enumerate(temp_tracker_entrances.keys()):
temp_data = {
"Entrance": temp_tracker_entrances[entrance],
"EntranceNum": floor(int(i)%3)
}
temp_tracker_entrances[entrance] = temp_data
tracker_current_scene_data["Entrances"] = temp_tracker_entrances
context = {
"debug": tracker_debug,
"totals": tracker_totals,
"scene": tracker_current_scene,
"scene_data": tracker_current_scene_data
}
return HttpResponse(template.render(context, request))

View File

View File

@ -0,0 +1,16 @@
"""
ASGI config for tunictracker 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.0/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tunictracker.settings')
application = get_asgi_application()

View File

@ -0,0 +1,132 @@
"""
Django settings for tunictracker project.
Generated by 'django-admin startproject' using Django 5.0.2.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/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.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-ae-fwu3z$wexeiac4ggt0l@x1*uq5v9-q&$y#frf85xli)bo8f'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'tracker',
'tailwind',
'werefoxtheme',
]
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 = 'tunictracker.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'tunictracker.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/5.0/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.0/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.0/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
TAILWIND_APP_NAME = 'werefoxtheme'
INTERNAL_IPS = [
"127.0.0.1",
]

View File

@ -0,0 +1,23 @@
"""
URL configuration for tunictracker project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("", include("tracker.urls")),
path('admin/', admin.site.urls),
]

View File

@ -0,0 +1,16 @@
"""
WSGI config for tunictracker 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.0/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tunictracker.settings')
application = get_wsgi_application()

View File

View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class WerefoxthemeConfig(AppConfig):
name = 'werefoxtheme'

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
node_modules

View File

@ -0,0 +1,28 @@
{
"name": "werefoxtheme",
"version": "3.8.0",
"description": "",
"scripts": {
"start": "npm run dev",
"build": "npm run build:clean && npm run build:tailwind",
"build:clean": "rimraf ../static/css/dist",
"build:tailwind": "cross-env NODE_ENV=production tailwindcss --postcss -i ./src/styles.css -o ../static/css/dist/styles.css --minify",
"dev": "cross-env NODE_ENV=development tailwindcss --postcss -i ./src/styles.css -o ../static/css/dist/styles.css -w",
"tailwindcss": "node ./node_modules/tailwindcss/lib/cli.js"
},
"keywords": [],
"author": "",
"license": "MIT",
"devDependencies": {
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.10",
"cross-env": "^7.0.3",
"postcss": "^8.4.32",
"postcss-import": "^15.1.0",
"postcss-nested": "^6.0.1",
"postcss-simple-vars": "^7.0.1",
"rimraf": "^5.0.5",
"tailwindcss": "^3.4.0"
}
}

View File

@ -0,0 +1,7 @@
module.exports = {
plugins: {
"postcss-import": {},
"postcss-simple-vars": {},
"postcss-nested": {}
},
}

View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -0,0 +1,96 @@
/**
* This is a minimal config.
*
* If you need the full config, get it from here:
* https://unpkg.com/browse/tailwindcss@latest/stubs/defaultConfig.stub.js
*/
module.exports = {
content: [
/**
* HTML. Paths to Django template files that will contain Tailwind CSS classes.
*/
/* Templates within theme app (<tailwind_app_name>/templates), e.g. base.html. */
"../templates/**/*.html",
/*
* Main templates directory of the project (BASE_DIR/templates).
* Adjust the following line to match your project structure.
*/
"../../templates/**/*.html",
/*
* Templates in other django apps (BASE_DIR/<any_app_name>/templates).
* Adjust the following line to match your project structure.
*/
"../../**/templates/**/*.html",
/**
* JS: If you use Tailwind CSS in JavaScript, uncomment the following lines and make sure
* patterns match your project structure.
*/
/* JS 1: Ignore any JavaScript in node_modules folder. */
// '!../../**/node_modules',
/* JS 2: Process all JavaScript files in the project. */
// '../../**/*.js',
/**
* Python: If you use Tailwind CSS classes in Python, uncomment the following line
* and make sure the pattern below matches your project structure.
*/
// '../../**/*.py'
],
theme: {
container: {
center: true,
padding: {
DEFAULT: "1rem",
xl: "0rem",
},
},
extend: {
fontFamily: {
nerd: ["DejaVuSansMono"],
},
colors: {
bluelight: {
DEFAULT: "#317eb1",
translucent: {
DEFAULT: "#317eb180",
dark: "#2facff40",
},
dark: "#2facff80",
},
greenlight: {
DEFAULT: "#339649",
translucent: "#33964930",
},
"trans-pride": {
cyan: {
DEFAULT: "#e4faff",
translucent: "#e4faff30",
},
white: {
DEFAULT: "#eeeeeeff",
translucent: "#eeeeee30",
},
pink: {
DEFAULT: "#ffecf9",
translucent: "#ffecf930",
},
},
},
},
},
plugins: [
/**
* '@tailwindcss/forms' is the forms plugin that provides a minimal styling
* for forms. If you don't like it or have own styling for forms,
* comment the line below to disable '@tailwindcss/forms'.
*/
require("@tailwindcss/forms"),
require("@tailwindcss/typography"),
require("@tailwindcss/aspect-ratio"),
],
};

View File

@ -0,0 +1,19 @@
{% load static tailwind_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Django Tailwind</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{% tailwind_css %}
</head>
<body class="bg-gray-50 font-serif leading-normal tracking-normal">
<div class="container mx-auto">
<section class="flex items-center justify-center h-screen">
<h1 class="text-5xl">Django + Tailwind = ❤️</h1>
</section>
</div>
</body>
</html>