15 Commits

Author SHA1 Message Date
10aeabdb83 increase allowed range for prediction 2023-10-05 02:29:39 +02:00
5604fac1b2 readjust step in predict and add dateformating function 2023-10-05 02:19:52 +02:00
89e802aa57 add pycache to gitignore 2023-10-04 00:13:07 +02:00
06af95ce57 fix prediction 2023-10-04 00:11:21 +02:00
ba69c2a97f add functions.py and prediction checks 2023-10-03 23:45:48 +02:00
ff088a6a24 bug fixing 2023-10-03 22:52:40 +02:00
4d0869ddf7 Merge remote-tracking branch 'origin/moreOnStyle' 2023-10-03 22:04:05 +02:00
a872c70e93 add dynamic values to sms.html 2023-10-03 22:03:13 +02:00
hugo
20db73836c Style fixes and gitignore 2023-10-03 21:56:20 +02:00
05bc3112d6 Merge remote-tracking branch 'origin/frontend' 2023-10-03 21:32:46 +02:00
a3b7ff3f9f add checks for ticket lenght and format 2023-10-03 21:31:56 +02:00
62833a2bd6 fix wording and spacing 2023-10-03 21:25:52 +02:00
be7dcf5903 add retrival of last ticket 2023-10-03 21:24:01 +02:00
e794fc6032 add sql support 2023-10-03 21:02:33 +02:00
17ab0b1840 fix post request 2023-10-03 20:30:21 +02:00
13 changed files with 156 additions and 62 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
__pycacahe__/*
freeriders/__pycacahe__/*
instance/

View File

@@ -1,3 +1,10 @@
# freeriders # freeriders
Web app for tracking current ticket numbers Web app for tracking current ticket numbers
# Architecture
- keep all ticket numbers and timestamps in SQL table "tickets"
- display last ticket number
- don't allow tickets that are out of probable ticket number range
- if last submited ticket is timestamped more then 90 minutes ago, try to predict the next number

View File

@@ -4,7 +4,7 @@ Priority: optional
Architecture: all Architecture: all
Essential: no Essential: no
Installed-Size: 2000 Installed-Size: 2000
Depends: python3-flask, gunicorn Depends: gunicorn, python3-flask-sqlalchemy
Homepage: https://gitea.dmz.rs/Decentrala/freeriders Homepage: https://gitea.dmz.rs/Decentrala/freeriders
Maintainer: Decentrala <dmz@dmz.rs> Maintainer: Decentrala <dmz@dmz.rs>
Description: Web app that tracks bus transport ticket numbers Description: Web app that tracks bus transport ticket numbers

View File

@@ -1,5 +1,16 @@
from flask import Flask from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os # if you wanna have db credenitalas in os.environ
app = Flask(__name__) app = Flask(__name__)
# SQLAlchemy setup
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///freeriders.db'
#MySql setup
#app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://user:pass@localhost/dbname'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
from freeriders import routes from freeriders import routes

21
freeriders/functions.py Normal file
View File

@@ -0,0 +1,21 @@
import time
import datetime
def datetounix(day, month, year, hour, minute, second):
seconds = datetime.datetime(year, month, day, hour, minute, second).timestamp()
return int(seconds)
def formatprefix2(number):
return "{:02d}".format(number)
def formatprefix10(number):
return "{:010d}".format(number)
def predict(timestamp):
base_ticket = 7157662
base_timestamp = 1695887564
step = 0.688
ticket = base_ticket + (timestamp - base_timestamp) * step
return int(ticket)

6
freeriders/models.py Normal file
View File

@@ -0,0 +1,6 @@
from freeriders import db
class Tickets(db.Model):
id = db.Column(db.Integer, primary_key=True)
ticket = db.Column(db.Integer, nullable=False)
timestamp = db.Column(db.Integer, nullable=False)

View File

@@ -1,10 +1,58 @@
from flask import render_template, request, redirect from flask import render_template, request, redirect
from freeriders import app from freeriders import app, db
from freeriders.functions import formatprefix2,formatprefix10, predict
from freeriders.models import Tickets
from datetime import datetime
import time
@app.route('/', methods=['POST', 'GET']) @app.route('/sms', methods=['GET'])
def changepassword(): def sms():
if request.method == 'GET': if request.method == 'GET':
return render_template('index.html') timenow = int(time.time())
elif request.method == 'POST':
try:
lastticket = Tickets.query.order_by(Tickets.timestamp.desc()).first()
if lastticket.timestamp < timenow - (90 * 60):
lastticket = formatprefix10(predict(timenow))
else:
lastticket = formatprefix10(lastticket.ticket)
date = datetime.now()
datenow = f'{formatprefix2(date.day)}.{formatprefix2(date.month)}.{date.year}'
timenow = f'{formatprefix2(date.hour)}:{formatprefix2(date.minute)}:{formatprefix2(date.second)}'
return render_template('sms.html', ticket = lastticket, date = datenow, time = timenow)
except:
return 'Error retriving last ticket'
else:
return 'HTTP request method not recogniezed'
@app.route('/submit', methods=['POST', 'GET'])
def submit():
PREDICTTIMERANGE = 60 * 60 * 24
if request.method == 'GET':
return render_template('submit.html')
elif request.method == 'POST':
timenow = int(time.time())
ticket_input = request.form['ticket']
if ticket_input.isdigit() and len(ticket_input) == 10 :
if int(ticket_input) < predict(timenow + PREDICTTIMERANGE ) and int(ticket_input) > predict(timenow - PREDICTTIMERANGE ) :
ticket = Tickets(ticket = int(ticket_input), timestamp = timenow)
else:
print(int(ticket_input))
print(predict(timenow - PREDICTTIMERANGE))
print(predict(timenow + PREDICTTIMERANGE))
print(predict(timenow))
return 'Ticket number is in unexpected range.'
else:
return 'Ticket format is wrong. Only 10 digits allowed.'
try:
db.session.add(ticket)
db.session.commit()
return 'Ticket added'
except:
return 'Adding ticket failed'
else: else:
return 'HTTP request method not recogniezed' return 'HTTP request method not recogniezed'

View File

@@ -1,9 +1,9 @@
:root { :root {
--border-radus: 1rem; --border-radus: 1rem;
--background: #EEE; --background: #F9F9F9;
--header-background: #DDD; --header-background: #EEE;
--header-height: 3rem; --header-height: 3rem;
--input-bar-height: 2rem; --input-bar-height: 3rem;
} }
body{ body{
@@ -14,14 +14,13 @@ body{
} }
main { main {
max-width: 400px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-self: flex-start; align-self: flex-start;
gap: 1rem; gap: 1rem;
margin: 0 auto; margin: 0 auto;
padding: 1rem 0.5rem; padding: 2rem 0.5rem;
height: calc(100vh - 5rem); height: calc(100vh - var(--header-height) - var(--input-bar-height));
overflow-y: scroll; overflow-y: scroll;
box-sizing: border-box; box-sizing: border-box;
} }
@@ -30,22 +29,25 @@ header {
background-color: var(--header-background); background-color: var(--header-background);
display: flex; display: flex;
flex-direction: row; flex-direction: row;
padding: 1rem; align-items: center;
padding: 0 1rem;
gap: 1rem; gap: 1rem;
font-weight: bold; font-weight: bold;
width: 100vw; width: 100vw;
height: var(header-height); height: var(--header-height);
box-sizing: border-box; box-sizing: border-box;
} }
footer { footer {
width: 100vw; width: 100vw;
height: var(input-bar-height); height: var(--input-bar-height);
background-color: #FDD; background-color: var(--background);
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center;
padding: 0 1rem; padding: 0 1rem;
box-sizing: border-box; box-sizing: border-box;
gap: 1rem;
} }
.request { .request {
@@ -68,3 +70,11 @@ footer {
align-self: center; align-self: center;
margin-top: 0.5rem; margin-top: 0.5rem;
} }
.textbox{
background-color: var(--header-background);
width: 80%;
height: 1rem;
padding: 0.2rem;
border-radius: 2rem;
}

View File

@@ -1,14 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/styles/style.css">
<link rel="shortcut icon" href="/img/favicon.ico" type="image/x-icon">
<title>Ticket tracking</title>
</head>
<body>
<main>
</main>
</body>
</html>

View File

@@ -4,7 +4,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Karta</title> <title>Karta</title>
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="/static/style.css">
</head> </head>
<body> <body>
<header> <header>
@@ -20,35 +20,8 @@
U Beogradu, za broj telefona ste kupili U Beogradu, za broj telefona ste kupili
VREMENSKU KARTU OD 90 MINUTA U ZONI A po VREMENSKU KARTU OD 90 MINUTA U ZONI A po
ceni od 50 din + osnovna cena poruke, ceni od 50 din + osnovna cena poruke,
koja vazi do 03.10.2023, 09:42:54. koja vazi do {{ date }}, {{ time }}.
Karta broj: 0000343232. Karta broj: {{ ticket }}.
Placanjem operateru izmirujete dugovanja
za ovu kartu prema JKP Naplata prevozne
usluge Beograd. Sacuvajte ovu poruku.
</section>
<section class='request'>
A90
</section>
<section class='ticket'>
U Beogradu, za broj telefona ste kupili
VREMENSKU KARTU OD 90 MINUTA U ZONI A po
ceni od 50 din + osnovna cena poruke,
koja vazi do 03.10.2023, 09:42:54.
Karta broj: 0000343232.
Placanjem operateru izmirujete dugovanja
za ovu kartu prema JKP Naplata prevozne
usluge Beograd. Sacuvajte ovu poruku.
</section>
<section class='date'>08:23</section>
<section class='request'>
A90
</section>
<section class='ticket'>
U Beogradu, za broj telefona ste kupili
VREMENSKU KARTU OD 90 MINUTA U ZONI A po
ceni od 50 din + osnovna cena poruke,
koja vazi do 03.10.2023, 09:42:54.
Karta broj: 0000343232.
Placanjem operateru izmirujete dugovanja Placanjem operateru izmirujete dugovanja
za ovu kartu prema JKP Naplata prevozne za ovu kartu prema JKP Naplata prevozne
usluge Beograd. Sacuvajte ovu poruku. usluge Beograd. Sacuvajte ovu poruku.

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Submit</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<main>
<form action="/submit" method="POST">
<label for="ticket">ticket</label>
<input type="text" name="ticket" id="ticket" placeholder="1234567890" required>
<button> Submit </button>
</form>
</main>
</body>
</html>

10
init_db.py Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env python3
from freeriders import db
print('[i] Trying to create databse...')
try:
db.create_all()
print('[+] Success you can proceed with deployment!')
except:
print('[-] Creating db failed :/')

View File

@@ -1 +1,2 @@
flask flask
SQLAlchemy