feat: init commit

This commit is contained in:
Alex Wellnitz 2024-09-19 12:24:21 +02:00
commit 9d3b42a300
7 changed files with 485 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.venv/
__pycache__/
results/
profiles/
simc/

14
README.md Normal file
View File

@ -0,0 +1,14 @@
# SIM Free
## Description
### Installation
```bash
python -m venv .venv
source .venv/bin/activate
```
### Run
```bash
fastapi run main.py
```

63
main.py Normal file
View File

@ -0,0 +1,63 @@
import os
import logging
import uuid
from simcrunner import Simc, JsonExport, Arguments, Profile
from typing import Union, Annotated
from fastapi import FastAPI, Form
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from starlette.responses import FileResponse
from simcrunner.simc import HtmlExport
# SIMC Settings
logging.basicConfig(level=logging.INFO)
simc_path = os.path.join('tests', 'simc')
runner = Simc(simc_path=simc_path)
app = FastAPI()
app.mount("/static", StaticFiles(directory="templates/static"), name="static")
# ROUTES
@app.get("/")
def read_root():
index_path = os.path.join('templates', 'index.html')
return FileResponse(index_path)
@app.post("/sim/current_gear")
async def simulate_current_gear(simcprofile: Annotated[str, Form()]):
sim_args = create_sim_arguments(simcprofile)
export_path = create_html_export()
html_export = HtmlExport(export_path)
(runner
.add_args(sim_args)
.add_args('target_error=0.05', threads=4)
.add_args(html_export)
.run())
return FileResponse(export_path)
# HELPER Functions
def create_profile(profile_path: str, profile_data: str):
with open(profile_path, 'w') as file:
# Write content to the file
file.write(profile_data)
def create_html_export():
rand_uuid = uuid.uuid4()
export_path = os.path.join('results', str(rand_uuid)+'.html')
return export_path
def create_sim_arguments(profile_data: str):
rand_uuid = uuid.uuid4()
profile_path = os.path.join('profiles', str(rand_uuid)+'.simc')
create_profile(profile_path, profile_data)
profile = Profile(profile_path)
args = Arguments(profile, iterations=1000)
return args

222
templates/index.html Normal file
View File

@ -0,0 +1,222 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>SIM-Free</title>
<script src="/static/color-modes.js"></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@docsearch/css@3"
/>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
crossorigin="anonymous"
/>
<meta name="theme-color" content="#712cf9" />
<link rel="stylesheet" href="static/styles.css" />
</head>
<body class="bg-body-tertiary">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#">SIM-Free</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div
class="collapse navbar-collapse"
id="navbarSupportedContent"
>
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a
class="nav-link active"
aria-current="page"
href="#"
>Home</a
>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
</ul>
<form class="d-flex" role="search">
<input
class="form-control me-2"
type="search"
placeholder="Search"
aria-label="Search"
/>
<button class="btn btn-outline-success" type="submit">
Search
</button>
</form>
</div>
</div>
</nav>
<div
class="dropdown position-fixed bottom-0 end-0 mb-3 me-3 bd-mode-toggle"
>
<button
class="btn btn-bd-primary py-2 dropdown-toggle d-flex align-items-center"
id="bd-theme"
type="button"
aria-expanded="false"
data-bs-toggle="dropdown"
aria-label="Toggle theme (dark)"
>
<svg class="bi my-1 theme-icon-active" width="1em" height="1em">
<use href="#moon-stars-fill"></use>
</svg>
<span class="visually-hidden" id="bd-theme-text"
>Toggle theme</span
>
</button>
<ul
class="dropdown-menu dropdown-menu-end shadow"
aria-labelledby="bd-theme-text"
>
<li>
<button
type="button"
class="dropdown-item d-flex align-items-center"
data-bs-theme-value="light"
aria-pressed="false"
>
<svg
class="bi me-2 opacity-50"
width="1em"
height="1em"
>
<use href="#sun-fill"></use>
</svg>
Light
<svg class="bi ms-auto d-none" width="1em" height="1em">
<use href="#check2"></use>
</svg>
</button>
</li>
<li>
<button
type="button"
class="dropdown-item d-flex align-items-center active"
data-bs-theme-value="dark"
aria-pressed="true"
>
<svg
class="bi me-2 opacity-50"
width="1em"
height="1em"
>
<use href="#moon-stars-fill"></use>
</svg>
Dark
<svg class="bi ms-auto d-none" width="1em" height="1em">
<use href="#check2"></use>
</svg>
</button>
</li>
<li>
<button
type="button"
class="dropdown-item d-flex align-items-center"
data-bs-theme-value="auto"
aria-pressed="false"
>
<svg
class="bi me-2 opacity-50"
width="1em"
height="1em"
>
<use href="#circle-half"></use>
</svg>
Auto
<svg class="bi ms-auto d-none" width="1em" height="1em">
<use href="#check2"></use>
</svg>
</button>
</li>
</ul>
</div>
<div class="container">
<main>
<div class="py-5 text-center">
<!-- <img
class="d-block mx-auto mb-4"
src="/docs/5.3/assets/brand/bootstrap-logo.svg"
alt=""
width="72"
height="57"
/> -->
<h2>Simulate form</h2>
<p class="lead">
Copy/paste the text from the SimulationCraft addon.
</p>
</div>
<div class="row g-5">
<div class="col-md-7 col-lg-12">
<h4 class="mb-3">Sim Data</h4>
<form action="/sim/current_gear" method="POST">
<div class="row g-3">
<div class="col-sm-12">
<div class="mb-3">
<label
for="simcprofile"
class="form-label"
>SimC Profile</label
>
<textarea
class="form-control"
id="simcprofile"
name="simcprofile"
rows="12"
></textarea>
</div>
</div>
</div>
<div class="col-sm-4">
<button
class="w-100 btn btn-primary btn-lg"
type="submit"
>
Continue to Simulate
</button>
</div>
</form>
</div>
</div>
</main>
<footer
class="my-5 pt-5 text-body-secondary text-center text-small"
>
<p class="mb-1">© 20172024 Company Name</p>
<ul class="list-inline">
<li class="list-inline-item"><a href="#">Privacy</a></li>
<li class="list-inline-item"><a href="#">Terms</a></li>
<li class="list-inline-item"><a href="#">Support</a></li>
</ul>
</footer>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
crossorigin="anonymous"
></script>
<script src="static/main.js"></script>
</body>
</html>

View File

@ -0,0 +1,92 @@
/*!
* Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
*/
(() => {
"use strict";
const getStoredTheme = () => localStorage.getItem("theme");
const setStoredTheme = (theme) => localStorage.setItem("theme", theme);
const getPreferredTheme = () => {
const storedTheme = getStoredTheme();
if (storedTheme) {
return storedTheme;
}
return window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light";
};
const setTheme = (theme) => {
if (theme === "auto") {
document.documentElement.setAttribute(
"data-bs-theme",
window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light",
);
} else {
document.documentElement.setAttribute("data-bs-theme", theme);
}
};
setTheme(getPreferredTheme());
const showActiveTheme = (theme, focus = false) => {
const themeSwitcher = document.querySelector("#bd-theme");
if (!themeSwitcher) {
return;
}
const themeSwitcherText = document.querySelector("#bd-theme-text");
const activeThemeIcon = document.querySelector(".theme-icon-active use");
const btnToActive = document.querySelector(
`[data-bs-theme-value="${theme}"]`,
);
const svgOfActiveBtn = btnToActive
.querySelector("svg use")
.getAttribute("href");
document.querySelectorAll("[data-bs-theme-value]").forEach((element) => {
element.classList.remove("active");
element.setAttribute("aria-pressed", "false");
});
btnToActive.classList.add("active");
btnToActive.setAttribute("aria-pressed", "true");
activeThemeIcon.setAttribute("href", svgOfActiveBtn);
const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`;
themeSwitcher.setAttribute("aria-label", themeSwitcherLabel);
if (focus) {
themeSwitcher.focus();
}
};
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", () => {
const storedTheme = getStoredTheme();
if (storedTheme !== "light" && storedTheme !== "dark") {
setTheme(getPreferredTheme());
}
});
window.addEventListener("DOMContentLoaded", () => {
showActiveTheme(getPreferredTheme());
document.querySelectorAll("[data-bs-theme-value]").forEach((toggle) => {
toggle.addEventListener("click", () => {
const theme = toggle.getAttribute("data-bs-theme-value");
setStoredTheme(theme);
setTheme(theme);
showActiveTheme(theme, true);
});
});
});
})();

3
templates/static/main.js Normal file
View File

@ -0,0 +1,3 @@
//
// Place any custom JS here
//

View File

@ -0,0 +1,86 @@
/*
* Custom CSS
*/
:root {
--bs-body-bg: var(--bs-gray-100);
}
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
.b-example-divider {
width: 100%;
height: 3rem;
background-color: rgba(0, 0, 0, 0.1);
border: solid rgba(0, 0, 0, 0.15);
border-width: 1px 0;
box-shadow:
inset 0 0.5em 1.5em rgba(0, 0, 0, 0.1),
inset 0 0.125em 0.5em rgba(0, 0, 0, 0.15);
}
.b-example-vr {
flex-shrink: 0;
width: 1.5rem;
height: 100vh;
}
.bi {
vertical-align: -0.125em;
fill: currentColor;
}
.nav-scroller {
position: relative;
z-index: 2;
height: 2.75rem;
overflow-y: hidden;
}
.nav-scroller .nav {
display: flex;
flex-wrap: nowrap;
padding-bottom: 1rem;
margin-top: -1px;
overflow-x: auto;
text-align: center;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
.btn-bd-primary {
--bd-violet-bg: #712cf9;
--bd-violet-rgb: 112.520718, 44.062154, 249.437846;
--bs-btn-font-weight: 600;
--bs-btn-color: var(--bs-white);
--bs-btn-bg: var(--bd-violet-bg);
--bs-btn-border-color: var(--bd-violet-bg);
--bs-btn-hover-color: var(--bs-white);
--bs-btn-hover-bg: #6528e0;
--bs-btn-hover-border-color: #6528e0;
--bs-btn-focus-shadow-rgb: var(--bd-violet-rgb);
--bs-btn-active-color: var(--bs-btn-hover-color);
--bs-btn-active-bg: #5a23c8;
--bs-btn-active-border-color: #5a23c8;
}
.bd-mode-toggle {
z-index: 1500;
}
.bd-mode-toggle .dropdown-menu .active .bi {
display: block !important;
}