git init / upload 🚀

This commit is contained in:
2025-03-30 19:59:45 +02:00
commit 6e0a8ea40c
10 changed files with 404 additions and 0 deletions

185
.gitignore vendored Normal file
View File

@@ -0,0 +1,185 @@
# Created by .ignore support plugin (hsz.mobi)
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# 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/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# IPython Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# dotenv
.env
# virtualenv
venv/
ENV/
# Spyder project settings
.spyderproject
# Rope project settings
.ropeproject
### VirtualEnv template
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
[Bb]in
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ll]ocal
[Ss]cripts
pyvenv.cfg
.venv
pip-selfcheck.json
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# idea folder, uncomment if you don't need it
# .idea

8
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyInterpreterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

View File

@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.13 (oe-html-viewer)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (oe-html-viewer)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/oe-html-viewer.iml" filepath="$PROJECT_DIR$/.idea/oe-html-viewer.iml" />
</modules>
</component>
</project>

16
.idea/oe-html-viewer.iml generated Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="Flask">
<option name="enabled" value="true" />
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.13 (oe-html-viewer)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Jinja2" />
</component>
</module>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

67
README.md Normal file
View File

@@ -0,0 +1,67 @@
# OE HTML viewer
Simple Python script to serve the exported HTML results file from the SportSoftware OE application on the local network.
## Getting Started
### Prerequisites
- Python 3.x
- pip
- virtualenv
### Installation
1. Clone the repository:
```sh
git clone <repository_url>
cd <repository_name>
```
2. Create a virtual environment:
```sh
python -m venv .venv
```
3. Activate the virtual environment:
- On Windows:
```sh
.venv\Scripts\activate
```
- On macOS/Linux:
```sh
source .venv/bin/activate
```
4. Install the required packages:
```sh
pip install -r requirements.txt
```
### Running the Application
1. Start the Flask application:
```sh
python main.py
```
2. Open your web browser and navigate to `http://localhost:80`.
### Variables
The following variables can be found at the top of the `main.py` script:
- `html_file_path`: Path to the HTML file to be served.
- `host`: Host address for the Flask application. Leave at `0.0.0.0` for avability at all network interfaces (localhost / LAN)
- `port`: Port number for the Flask application.
- `is_oe11`: Boolean flag for encoding (True for OE11, False for OE12).
- `scroll_pixels`: Number of pixels to scroll each interval.
- `scroll_interval`: Time interval (in seconds) between each scroll.
- `bottom_wait_time`: Time to wait (in seconds) at the bottom of the page before reloading.
- `top_wait_time`: Time to wait (in seconds) at the top of the page before starting to scroll.
- `reload_interval`: Time interval (in seconds) to reload the page if no scrolling is needed. Set this value minimum 1 seconds larger than the export interval in OE.
### License
This project is licensed under the MIT License - see the `LICENSE` file for details.

95
main.py Normal file
View File

@@ -0,0 +1,95 @@
import os
from flask import Flask
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
# -------------- VARIABLES --------------
html_file_path = r'C:\<PATH>'
host = '0.0.0.0' # http://localhost OR http://<ip_address>
port = 80
is_oe11 = True # if using OE11 set it to True, for OE12 set it to False (encoding)
scroll_pixels = 100
scroll_interval = 3 # seconds
bottom_wait_time = 3 # seconds
top_wait_time = 3 # seconds
reload_interval = 35 # seconds
# -------------- END VARIABLES --------------
app = Flask(__name__)
class FileChangeHandler(FileSystemEventHandler):
def __init__(self, app):
self.app = app
def on_modified(self, event):
if event.src_path == html_file_path:
with self.app.app_context():
self.app.config['TEMPLATES_AUTO_RELOAD'] = True
@app.route('/')
def serve_html():
with open(html_file_path, 'r', encoding= ('latin-1' if is_oe11 else 'utf-8') ) as file:
content = file.read()
content += f'''
<style>
html {{
scroll-behavior: smooth;
}}
</style>
<script>
let scrollAmount = {scroll_pixels};
let scrollInterval = {scroll_interval} * 1000;
let bottomWaitTime = {bottom_wait_time} * 1000;
let topWaitTime = {top_wait_time} * 1000;
let reloadInterval = {reload_interval} * 1000;
let scrollPos = 0;
let scrollingDown = true;
function autoScroll() {{
if (scrollingDown) {{
window.scrollBy(0, scrollAmount);
scrollPos += scrollAmount;
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {{
scrollingDown = false;
setTimeout(reloadPage, bottomWaitTime);
return;
}}
}} else {{
window.scrollTo(0, 0);
scrollPos = 0;
scrollingDown = true;
setTimeout(autoScroll, topWaitTime);
return;
}}
setTimeout(autoScroll, scrollInterval);
}}
function reloadPage() {{
window.scrollTo(0, 0);
setTimeout(() => {{
location.reload();
}}, 100);
}}
window.onload = function() {{
window.scrollTo(0, 0);
if (document.body.scrollHeight <= window.innerHeight) {{
setTimeout(reloadPage, reloadInterval);
}} else {{
setTimeout(autoScroll, topWaitTime);
}}
}};
</script>
'''
return content
if __name__ == '__main__':
event_handler = FileChangeHandler(app)
observer = Observer()
observer.schedule(event_handler, path=os.path.dirname(html_file_path), recursive=False)
observer.start()
try:
app.run(host=host, port=port)
except KeyboardInterrupt:
observer.stop()
observer.join()