first commit

This commit is contained in:
0ceanSlim 2024-01-30 11:06:00 -05:00
commit 14d3b7506e
12 changed files with 905 additions and 0 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) [2024] [OceanSlim]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

95
app.py Normal file
View File

@ -0,0 +1,95 @@
from flask import Flask, render_template, g, abort, request, jsonify
import sqlite3
app = Flask(__name__)
DATABASE = 'static/data/monsters.db'
def connect_db():
return sqlite3.connect(DATABASE)
@app.before_request
def before_request():
g.db = connect_db()
@app.teardown_request
def teardown_request(exception):
if hasattr(g, 'db'):
g.db.close()
@app.route("/")
def show_index():
return render_template("index.html")
@app.route('/get_families')
def get_families():
cursor = g.db.cursor()
cursor.execute('SELECT DISTINCT name FROM families')
families = [row[0] for row in cursor.fetchall()]
return jsonify(families)
@app.route('/get_monsters')
def get_monsters():
selected_family = request.args.get('family')
cursor = g.db.cursor()
if selected_family:
cursor.execute('''
SELECT name FROM monsters
WHERE family_id = (SELECT id FROM families WHERE name = ?)
''', (selected_family,))
else:
cursor.execute('SELECT DISTINCT name FROM monsters')
monsters = [row[0] for row in cursor.fetchall()]
return jsonify(monsters)
@app.route('/monster/<monster_name>')
def monster_info(monster_name):
cursor = g.db.cursor()
# Retrieve monster information from the database based on name
cursor.execute('''
SELECT
monsters.id, monsters.name, families.name AS family, monsters.in_story,
monsters.agl, monsters.int, monsters.maxlvl, monsters.atk, monsters.mp,
monsters.exp, monsters.hp, monsters.def
FROM
monsters
JOIN families ON monsters.family_id = families.id
WHERE
monsters.name = ?
''', (monster_name,))
monster_info = cursor.fetchone()
if monster_info is None:
abort(404)
# Retrieve skills for the monster
cursor.execute('SELECT skill FROM skills WHERE monster_id = ?', (monster_info[0],))
skills = [row[0] for row in cursor.fetchall()]
# Retrieve spawn locations for the monster
cursor.execute('SELECT map, description FROM spawn_locations WHERE monster_id = ?', (monster_info[0],))
spawn_locations = [{'map': row[0], 'description': row[1]} for row in cursor.fetchall()]
return render_template('monsters.html', monster={
'id': monster_info[0],
'name': monster_info[1],
'family': monster_info[2],
'in_story': 'Yes' if monster_info[3] else 'No',
'agl': monster_info[4],
'int': monster_info[5],
'maxlvl': monster_info[6],
'atk': monster_info[7],
'mp': monster_info[8],
'exp': monster_info[9],
'hp': monster_info[10],
'def': monster_info[11],
'skills': skills,
'spawn_locations': spawn_locations
})
if __name__ == '__main__':
app.run(debug=True)

72
readme.md Normal file
View File

@ -0,0 +1,72 @@
# Dragon Warrior Monsters 2 App
## Overview
This Flask app is designed to use data from Dragon Warrior Monsters 2 to create an intuitive web UI. The app allows users to lookup monster information, and eventually breeding pairs and skills. Inspired by the [dwm2-tools](https://github.com/MetroWind/dwm2-tools) project.
## Features
- Efficiently parse and display Dragon Warrior Monsters 2 game data.
- Simple and accessible codebase for developers with basic web skills.
- Fast development with Flask, allowing real-time changes while running.
- Seamless integration with SQLite database for scalability.
- Designer friendly Tailwind Styling
## Setup Instructions
### Prerequisites
- [Python](https://www.python.org/downloads/)
- [Tailwind CSS](https://github.com/tailwindlabs/tailwindcss/releases/latest)
### Installation
1. Clone the repository:
```bash
git clone https://github.com/0ceanslim/dwm2-app.git
cd dwm2-app
```
2. Install dependencies:
```bash
pip install -r requirements.txt
```
3. Run the Flask app:
```bash
python app.py
```
4. Open your browser and navigate to http://127.0.0.1:5000/.
### Tailwind CSS
To rebuild the styles when making changes, use:
```bash
tailwindcss -i static/style/input.css -o static/style/output.css --watch
```
## Development
Contributions and pull requests are welcome!
Fork the repository.
Create a new branch for your feature or bug fix.
Submit a pull request.
## To-Do List
- Add sprites for monsters.
- Enhance styling for a more polished appearance.
- Integrate a skills database with detailed descriptions.
### Future Enhancements
Discuss any planned features or enhancements for future development.
## License
This repository is provided under the MIT License. Feel free to use, modify, and distribute these scripts as needed. Contributions and improvements are welcome. ❤️
See the [LICENSE](LICENSE) file for details.
Acknowledgments
Special thanks to dwm2-tools for inspiration.

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
flask

BIN
static/data/monsters.db Normal file

Binary file not shown.

67
static/js/index.js Normal file
View File

@ -0,0 +1,67 @@
// static/js/app.js
document.addEventListener("DOMContentLoaded", function () {
const familyDropdown = document.getElementById("familyDropdown");
const monsterDropdown = document.getElementById("monsterDropdown");
const iframe = document.getElementById("monsterIframe");
// Initialize dropdowns and iframe
updateMonstersDropdown();
updateIframe();
// Fetch families data from the server
fetch("/get_families")
.then(response => response.json())
.then(data => {
populateDropdown(familyDropdown, data);
updateMonstersDropdown();
updateIframe();
})
.catch(error => console.error("Error fetching families:", error));
familyDropdown.addEventListener("change", function () {
updateMonstersDropdown();
updateIframe();
});
monsterDropdown.addEventListener("change", function () {
updateIframe();
});
function populateDropdown(dropdown, data) {
// Clear existing options
dropdown.innerHTML = '<option value="">All</option>';
// Populate dropdown options
data.forEach(item => {
const option = document.createElement("option");
option.value = item;
option.text = item;
dropdown.appendChild(option);
});
}
function updateMonstersDropdown() {
const selectedFamily = familyDropdown.value;
// Fetch monsters data from the server based on the selected family
fetch(`/get_monsters?family=${selectedFamily}`)
.then(response => response.json())
.then(data => populateDropdown(monsterDropdown, data))
.catch(error => console.error("Error fetching monsters:", error));
}
function updateIframe() {
const selectedFamily = familyDropdown.value;
const selectedMonster = monsterDropdown.value;
// Update iframe src based on selected family and monster
const iframeSrc = selectedMonster
? `/monster/${selectedMonster}`
: selectedFamily
? `/monster/${selectedFamily}`
: "about:blank";
iframe.src = iframeSrc;
}
});

5
static/style/input.css Normal file
View File

@ -0,0 +1,5 @@
@config "tailwind.config.js";
@tailwind base;
@tailwind components;
@tailwind utilities;

554
static/style/output.css Normal file
View File

@ -0,0 +1,554 @@
/*
! tailwindcss v3.3.6 | MIT License | https://tailwindcss.com
*/
/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/
*,
::before,
::after {
box-sizing: border-box;
/* 1 */
border-width: 0;
/* 2 */
border-style: solid;
/* 2 */
border-color: #e5e7eb;
/* 2 */
}
::before,
::after {
--tw-content: '';
}
/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
5. Use the user's configured `sans` font-feature-settings by default.
6. Use the user's configured `sans` font-variation-settings by default.
*/
html {
line-height: 1.5;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
-moz-tab-size: 4;
/* 3 */
-o-tab-size: 4;
tab-size: 4;
/* 3 */
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
/* 4 */
font-feature-settings: normal;
/* 5 */
font-variation-settings: normal;
/* 6 */
}
/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/
body {
margin: 0;
/* 1 */
line-height: inherit;
/* 2 */
}
/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/
hr {
height: 0;
/* 1 */
color: inherit;
/* 2 */
border-top-width: 1px;
/* 3 */
}
/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
/*
Remove the default font size and weight for headings.
*/
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
/*
Reset links to optimize for opt-in styling instead of opt-out.
*/
a {
color: inherit;
text-decoration: inherit;
}
/*
Add the correct font weight in Edge and Safari.
*/
b,
strong {
font-weight: bolder;
}
/*
1. Use the user's configured `mono` font-family by default.
2. Use the user's configured `mono` font-feature-settings by default.
3. Use the user's configured `mono` font-variation-settings by default.
4. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
/* 1 */
font-feature-settings: normal;
/* 2 */
font-variation-settings: normal;
/* 3 */
font-size: 1em;
/* 4 */
}
/*
Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/
table {
text-indent: 0;
/* 1 */
border-color: inherit;
/* 2 */
border-collapse: collapse;
/* 3 */
}
/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
/* 1 */
font-feature-settings: inherit;
/* 1 */
font-variation-settings: inherit;
/* 1 */
font-size: 100%;
/* 1 */
font-weight: inherit;
/* 1 */
line-height: inherit;
/* 1 */
color: inherit;
/* 1 */
margin: 0;
/* 2 */
padding: 0;
/* 3 */
}
/*
Remove the inheritance of text transform in Edge and Firefox.
*/
button,
select {
text-transform: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/
button,
[type='button'],
[type='reset'],
[type='submit'] {
-webkit-appearance: button;
/* 1 */
background-color: transparent;
/* 2 */
background-image: none;
/* 2 */
}
/*
Use the modern Firefox focus style for all focusable elements.
*/
:-moz-focusring {
outline: auto;
}
/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/
:-moz-ui-invalid {
box-shadow: none;
}
/*
Add the correct vertical alignment in Chrome and Firefox.
*/
progress {
vertical-align: baseline;
}
/*
Correct the cursor style of increment and decrement buttons in Safari.
*/
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/
[type='search'] {
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
/* 2 */
}
/*
Remove the inner padding in Chrome and Safari on macOS.
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button;
/* 1 */
font: inherit;
/* 2 */
}
/*
Add the correct display in Chrome and Safari.
*/
summary {
display: list-item;
}
/*
Removes the default spacing and border for appropriate elements.
*/
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
fieldset {
margin: 0;
padding: 0;
}
legend {
padding: 0;
}
ol,
ul,
menu {
list-style: none;
margin: 0;
padding: 0;
}
/*
Reset default styling for dialogs.
*/
dialog {
padding: 0;
}
/*
Prevent resizing textareas horizontally by default.
*/
textarea {
resize: vertical;
}
/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/
input::-moz-placeholder, textarea::-moz-placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
input::placeholder,
textarea::placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
/*
Set the default cursor for buttons.
*/
button,
[role="button"] {
cursor: pointer;
}
/*
Make sure disabled buttons don't get the pointer cursor.
*/
:disabled {
cursor: default;
}
/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
This can trigger a poorly considered lint error in some tools but is included by design.
*/
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
/* 1 */
vertical-align: middle;
/* 2 */
}
/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/
img,
video {
max-width: 100%;
height: auto;
}
/* Make elements with the HTML hidden attribute stay hidden by default */
[hidden] {
display: none;
}
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
.static {
position: static;
}
.font-bold {
font-weight: 700;
}
.text-blue-500 {
--tw-text-opacity: 1;
color: rgb(59 130 246 / var(--tw-text-opacity));
}

11
static/style/readme.md Normal file
View File

@ -0,0 +1,11 @@
# Development
For Tailwind to Rebuild the Output CSS, a watcher must be run to compile the new styling as pages are edited.
To do this run:
```bash
tailwindcss -i static/style/input.css -o static/style/output.css --watch
```
You must be in the `app` directory

View File

@ -0,0 +1,9 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./**/*.{html,js}"],
theme: {
extend: {},
},
plugins: [],
}

30
templates/index.html Normal file
View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DWM APP</title>
<link rel="stylesheet" href="../static/style/output.css">
<script src="{{ url_for('static', filename='js/index.js') }}"></script>
</head>
<body>
<h1 class="font-bold text-blue-500">Welcome to the Dragon Warrior Monsters 2 App</h1>
<div>
<h2 class="font-bold text-blue-500">Filter list by monster family<br>
Display monster stats in embed below</h2>
<label for="familyDropdown">Select Family:</label>
<select id="familyDropdown">
<option value="">All Families</option>
</select>
<label for="monsterDropdown">Select Monster:</label>
<select id="monsterDropdown">
<option value="">All Monsters</option>
</select>
<iframe id="monsterIframe" src="" width="fit" height="fit" frameborder="0"></iframe>
</div>
</body>
</html>

40
templates/monsters.html Normal file
View File

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Monster Information</title>
<link rel="stylesheet" href="../static/style/output.css">
</head>
<body>
<h1>Monster Information</h1>
<div>
<h2>{{ monster.name }}</h2>
<p><strong>Family:</strong> {{ monster.family }}</p>
<p><strong>In Story:</strong> {{ monster.in_story }}</p>
<p><strong>Stats:</strong></p>
<ul>
<li><strong>AGL:</strong> {{ monster.agl }}</li>
<li><strong>INT:</strong> {{ monster.int }}</li>
<li><strong>Max Level:</strong> {{ monster.maxlvl }}</li>
<li><strong>ATK:</strong> {{ monster.atk }}</li>
<li><strong>MP:</strong> {{ monster.mp }}</li>
<li><strong>EXP:</strong> {{ monster.exp }}</li>
<li><strong>HP:</strong> {{ monster.hp }}</li>
<li><strong>DEF:</strong> {{ monster.def }}</li>
</ul>
<p><strong>Skills:</strong></p>
<ul>
{% for skill in monster.skills %}
<li>{{ skill }}</li>
{% endfor %}
</ul>
<p><strong>Spawn Locations:</strong></p>
<ul>
{% for location in monster.spawn_locations %}
<li>{{ location.map }} - {{ location.description }}</li>
{% endfor %}
</ul>
</div>
</body>
</html>