mirror of
https://github.com/Redume/Kekkai.git
synced 2025-02-23 12:43:12 +03:00
refactor(chart): Move functions to separate files or folders to improve code structure.
This commit is contained in:
parent
110effaeb2
commit
85acbbb16c
5 changed files with 177 additions and 175 deletions
54
chart/function/create_chart.py
Normal file
54
chart/function/create_chart.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
from datetime import datetime
|
||||
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
from chart.function.gen_unique_name import generate_unique_name
|
||||
from ..database.server import create_pool
|
||||
|
||||
async def create_chart(from_currency: str, conv_currency: str, start_date: str, end_date: str) -> (str, None):
|
||||
pool = await create_pool()
|
||||
|
||||
start_date_obj = datetime.strptime(start_date, '%Y-%m-%d').date()
|
||||
end_date_obj = datetime.strptime(end_date, '%Y-%m-%d').date()
|
||||
|
||||
async with pool.acquire() as conn:
|
||||
data = await conn.fetch(
|
||||
'SELECT date, rate FROM currency '
|
||||
'WHERE (date BETWEEN $1 AND $2) AND from_currency = $3 AND conv_currency = $4',
|
||||
start_date_obj,
|
||||
end_date_obj,
|
||||
from_currency.upper(),
|
||||
conv_currency.upper()
|
||||
)
|
||||
|
||||
if not data or len(data) <= 1:
|
||||
return None
|
||||
|
||||
date, rate = [], []
|
||||
|
||||
for row in data:
|
||||
date.append(str(row['date']))
|
||||
rate.append(row['rate'])
|
||||
|
||||
if rate[0] < rate[-1]:
|
||||
plt.plot(date, rate, color='green', marker='o')
|
||||
elif rate[0] > rate[-1]:
|
||||
plt.plot(date, rate, color='red', marker='o')
|
||||
else:
|
||||
plt.plot(date, rate, color='grey')
|
||||
|
||||
plt.xlabel('Date')
|
||||
plt.ylabel('Rate')
|
||||
|
||||
fig = plt.gcf()
|
||||
fig.set_size_inches(18.5, 9.5)
|
||||
|
||||
name = await generate_unique_name(
|
||||
f'{from_currency.upper()}_{conv_currency.upper()}',
|
||||
datetime.now()
|
||||
)
|
||||
|
||||
fig.savefig(f'../charts/{name}.png')
|
||||
fig.clear()
|
||||
|
||||
return name
|
11
chart/function/gen_unique_name.py
Normal file
11
chart/function/gen_unique_name.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
import datetime
|
||||
import random
|
||||
import string
|
||||
|
||||
|
||||
async def generate_unique_name(currency_pair: str, date: datetime) -> str:
|
||||
date_str = date.strftime("%Y%m%d")
|
||||
random_suffix = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6))
|
||||
unique_name = f"{currency_pair}_{date_str}_{random_suffix}"
|
||||
|
||||
return unique_name
|
184
chart/main.py
184
chart/main.py
|
@ -1,34 +1,16 @@
|
|||
import os
|
||||
import psycopg2
|
||||
|
||||
import uvicorn
|
||||
|
||||
import yaml
|
||||
import matplotlib.pyplot as plt
|
||||
import datetime
|
||||
|
||||
import dateutil.relativedelta
|
||||
import random
|
||||
import string
|
||||
|
||||
from fastapi import FastAPI, Response, status, Request
|
||||
from psycopg2.extras import DictCursor
|
||||
|
||||
from fastapi import FastAPI
|
||||
from starlette.staticfiles import StaticFiles
|
||||
from middleware.plausible_analytics import PlausibleAnalytics
|
||||
|
||||
from chart.middleware.plausible_analytics import PlausibleAnalytics
|
||||
from chart.routes import get_chart, get_chart_period
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
config = yaml.safe_load(open('../config.yaml'))
|
||||
|
||||
con = psycopg2.connect(host=config['database']['host'],
|
||||
user=config['database']['user'],
|
||||
password=config['database']['password'],
|
||||
database=config['database']['name'],
|
||||
port=config['database']['port'])
|
||||
|
||||
cur = con.cursor(cursor_factory=DictCursor)
|
||||
con.autocommit = True
|
||||
config = yaml.safe_load(open('config.yaml'))
|
||||
|
||||
if not os.path.exists('../charts'):
|
||||
os.mkdir('../charts')
|
||||
|
@ -36,158 +18,16 @@ if not os.path.exists('../charts'):
|
|||
app.mount('/static/charts', StaticFiles(directory='../charts/'))
|
||||
app.middleware('http')(PlausibleAnalytics())
|
||||
|
||||
@app.get("/api/getChart/", status_code=status.HTTP_201_CREATED)
|
||||
async def get_chart(
|
||||
response: Response,
|
||||
request: Request,
|
||||
from_currency: str = None,
|
||||
conv_currency: str = None,
|
||||
start_date: str = None,
|
||||
end_date: str = None,
|
||||
):
|
||||
|
||||
if not from_currency or not conv_currency:
|
||||
response.status_code = status.HTTP_400_BAD_REQUEST
|
||||
return {
|
||||
'status': status.HTTP_400_BAD_REQUEST,
|
||||
'message': 'The from_currency and conv_currency fields are required.',
|
||||
}
|
||||
elif not start_date and not end_date:
|
||||
response.status_code = status.HTTP_400_BAD_REQUEST
|
||||
return {
|
||||
'status': status.HTTP_400_BAD_REQUEST,
|
||||
'message': 'The start_date and end_date fields are required.',
|
||||
}
|
||||
|
||||
|
||||
chart = await create_chart(from_currency, conv_currency, start_date, end_date)
|
||||
|
||||
if not chart:
|
||||
response.status_code = status.HTTP_404_NOT_FOUND
|
||||
return {'message': 'No data found.', 'status_code': status.HTTP_404_NOT_FOUND}
|
||||
|
||||
host = request.headers.get("host")
|
||||
url_schema = request.url.scheme
|
||||
|
||||
return {
|
||||
'status': status.HTTP_400_BAD_REQUEST,
|
||||
'message': f'{url_schema}://{host}/static/charts/{chart}.png',
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/getChart/{period}", status_code=status.HTTP_201_CREATED)
|
||||
async def get_chart_period(
|
||||
response: Response,
|
||||
request: Request,
|
||||
from_currency: str = None,
|
||||
conv_currency: str = None,
|
||||
period: str = None,
|
||||
):
|
||||
|
||||
if not from_currency or not conv_currency:
|
||||
response.status_code = status.HTTP_400_BAD_REQUEST
|
||||
return {
|
||||
'status': status.HTTP_400_BAD_REQUEST,
|
||||
'message': 'The from_currency and conv_currency fields are required.',
|
||||
}
|
||||
|
||||
if period not in ['week', 'month', 'quarter', 'year']:
|
||||
response.status_code = status.HTTP_400_BAD_REQUEST
|
||||
return {'message': 'Invalid period.', 'status_code': status.HTTP_400_BAD_REQUEST}
|
||||
|
||||
days, month, years = 0, 0, 0
|
||||
|
||||
if period == 'week':
|
||||
days = -7
|
||||
elif period == 'month':
|
||||
month = -1
|
||||
elif period == 'quarter':
|
||||
month = -3
|
||||
elif period == 'year':
|
||||
years = -1
|
||||
|
||||
end_date = datetime.datetime.now()
|
||||
start_date = end_date + dateutil.relativedelta.relativedelta(months=month, days=days, years=years)
|
||||
|
||||
chart = await create_chart(from_currency,
|
||||
conv_currency,
|
||||
start_date.strftime('%Y-%m-%d'),
|
||||
end_date.strftime('%Y-%m-%d')
|
||||
)
|
||||
|
||||
if not chart:
|
||||
response.status_code = status.HTTP_404_NOT_FOUND
|
||||
return {'message': 'No data found.', 'status_code': status.HTTP_404_NOT_FOUND}
|
||||
|
||||
host = request.headers.get("host")
|
||||
url_schema = request.url.scheme
|
||||
|
||||
return {
|
||||
'status': status.HTTP_201_CREATED,
|
||||
'message': f'{url_schema}://{host}/static/charts/{chart}.png',
|
||||
}
|
||||
|
||||
|
||||
async def create_chart(from_currency: str, conv_currency: str, start_date: str, end_date: str) -> (str, None):
|
||||
cur.execute('SELECT date, rate FROM currency WHERE (date BETWEEN %s AND %s) '
|
||||
'AND from_currency = %s AND conv_currency = %s ORDER BY date',
|
||||
[
|
||||
start_date, end_date,
|
||||
from_currency.upper(), conv_currency.upper()
|
||||
])
|
||||
|
||||
con.commit()
|
||||
data = cur.fetchall()
|
||||
|
||||
if not data or len(data) <= 1:
|
||||
return None
|
||||
|
||||
date, rate = [], []
|
||||
|
||||
for i in range(len(data)):
|
||||
date.append(str(data[i][0]))
|
||||
rate.append(data[i][1])
|
||||
|
||||
if rate[0] < rate[-1]:
|
||||
plt.plot(date, rate, color='green', marker='o')
|
||||
elif rate[0] > rate[-1]:
|
||||
plt.plot(date, rate, color='red', marker='o')
|
||||
else:
|
||||
plt.plot(date, rate, color='grey')
|
||||
|
||||
plt.xlabel('Date')
|
||||
plt.ylabel('Rate')
|
||||
|
||||
fig = plt.gcf()
|
||||
fig.set_size_inches(18.5, 9.5)
|
||||
|
||||
name = await generate_unique_name(
|
||||
f'{from_currency.upper()}_{conv_currency.upper()}',
|
||||
datetime.datetime.now()
|
||||
)
|
||||
|
||||
fig.savefig(f'../charts/{name}.png')
|
||||
fig.clear()
|
||||
|
||||
return name
|
||||
|
||||
|
||||
async def generate_unique_name(currency_pair: str, date: datetime) -> str:
|
||||
date_str = date.strftime("%Y%m%d")
|
||||
random_suffix = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6))
|
||||
unique_name = f"{currency_pair}_{date_str}_{random_suffix}"
|
||||
|
||||
return unique_name
|
||||
app.include_router(get_chart.router)
|
||||
app.include_router(get_chart_period.router)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
uvicorn.run(app,
|
||||
|
||||
uvicorn.run(
|
||||
app,
|
||||
host=config['server']['host'],
|
||||
port=3030,
|
||||
ssl_keyfile=config['server']['ssl']['private_key']
|
||||
if config['server']['ssl']['work']
|
||||
else None,
|
||||
ssl_certfile=config['server']['ssl']['cert']
|
||||
if config['server']['ssl']['work']
|
||||
else None
|
||||
ssl_keyfile=config['server']['ssl']['private_key'] if config['server']['ssl']['work'] else None,
|
||||
ssl_certfile=config['server']['ssl']['cert'] if config['server']['ssl']['work'] else None
|
||||
)
|
||||
|
|
34
chart/routes/get_chart.py
Normal file
34
chart/routes/get_chart.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
from fastapi import APIRouter, status, Request, Response
|
||||
|
||||
from chart.function.create_chart import create_chart
|
||||
from chart.routes.get_chart_period import prepare_chart_response
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/api/getChart/", status_code=status.HTTP_201_CREATED)
|
||||
async def get_chart(
|
||||
response: Response,
|
||||
request: Request,
|
||||
from_currency: str = None,
|
||||
conv_currency: str = None,
|
||||
start_date: str = None,
|
||||
end_date: str = None,
|
||||
):
|
||||
|
||||
if not from_currency or not conv_currency:
|
||||
response.status_code = status.HTTP_400_BAD_REQUEST
|
||||
return {
|
||||
'status': status.HTTP_400_BAD_REQUEST,
|
||||
'message': 'The from_currency and conv_currency fields are required.',
|
||||
}
|
||||
elif not start_date and not end_date:
|
||||
response.status_code = status.HTTP_400_BAD_REQUEST
|
||||
return {
|
||||
'status': status.HTTP_400_BAD_REQUEST,
|
||||
'message': 'The start_date and end_date fields are required.',
|
||||
}
|
||||
|
||||
|
||||
chart = await create_chart(from_currency, conv_currency, start_date, end_date)
|
||||
|
||||
return await prepare_chart_response(response, request, chart)
|
63
chart/routes/get_chart_period.py
Normal file
63
chart/routes/get_chart_period.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
from datetime import datetime
|
||||
import dateutil.relativedelta
|
||||
|
||||
from fastapi import APIRouter, status, Request, Response
|
||||
|
||||
from chart.function.create_chart import create_chart
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/api/getChart/{period}", status_code=status.HTTP_201_CREATED)
|
||||
async def get_chart_period(
|
||||
response: Response,
|
||||
request: Request,
|
||||
from_currency: str = None,
|
||||
conv_currency: str = None,
|
||||
period: str = None,
|
||||
):
|
||||
|
||||
if not from_currency or not conv_currency:
|
||||
response.status_code = status.HTTP_400_BAD_REQUEST
|
||||
return {
|
||||
'status': status.HTTP_400_BAD_REQUEST,
|
||||
'message': 'The from_currency and conv_currency fields are required.',
|
||||
}
|
||||
|
||||
if period not in ['week', 'month', 'quarter', 'year']:
|
||||
response.status_code = status.HTTP_400_BAD_REQUEST
|
||||
return {'message': 'Invalid period.', 'status_code': status.HTTP_400_BAD_REQUEST}
|
||||
|
||||
days, month, years = 0, 0, 0
|
||||
|
||||
if period == 'week':
|
||||
days = -7
|
||||
elif period == 'month':
|
||||
month = -1
|
||||
elif period == 'quarter':
|
||||
month = -3
|
||||
elif period == 'year':
|
||||
years = -1
|
||||
|
||||
end_date = datetime.now()
|
||||
start_date = end_date + dateutil.relativedelta.relativedelta(months=month, days=days, years=years)
|
||||
|
||||
chart = await create_chart(from_currency,
|
||||
conv_currency,
|
||||
start_date.strftime('%Y-%m-%d'),
|
||||
end_date.strftime('%Y-%m-%d')
|
||||
)
|
||||
|
||||
return await prepare_chart_response(response, request, chart)
|
||||
|
||||
async def prepare_chart_response(response: Response, request: Request, chart_name: str):
|
||||
if not chart_name:
|
||||
response.status_code = status.HTTP_404_NOT_FOUND
|
||||
return {'message': 'No data found.', 'status_code': status.HTTP_404_NOT_FOUND}
|
||||
|
||||
host = request.headers.get("host")
|
||||
url_schema = request.url.scheme
|
||||
|
||||
return {
|
||||
'status': status.HTTP_201_CREATED,
|
||||
'message': f'{url_schema}://{host}/static/charts/{chart_name}.png',
|
||||
}
|
Loading…
Add table
Reference in a new issue