#include "crow.h" #include "crow/middlewares/cors.h" #include #include #include using namespace sql; using namespace std; Driver *driver; Connection *con; Statement *stmt; PreparedStatement *prep_stmt; void exiting(){ delete con; delete stmt; } void connect(){ con = driver->connect(getenv("DBURL"),getenv("DBUSER"),getenv("DBPWD")); con->setSchema("practice"); stmt = con->createStatement(); } int main() { crow::App app; driver = get_driver_instance(); CROW_ROUTE(app, "/sessions").methods(crow::HTTPMethod::POST)([](const crow::request& req){ connect(); crow::json::wvalue status; auto request_body = crow::json::load(req.body); int new_session_id; if(request_body.has("comments")){ prep_stmt = con->prepareStatement("INSERT INTO practice_sessions (description, seconds, comments, practice_category_id) VALUES (?, ?, ?, ?) RETURNING id"); string description = request_body["description"].s(); int seconds = request_body["seconds"].i(); string comments = request_body["comments"].s(); int practice_category_id = request_body["practice_category_id"].i(); prep_stmt->setString(1, description); prep_stmt->setInt(2, seconds); prep_stmt->setString(3, comments); prep_stmt->setInt(4, practice_category_id); ResultSet *res = prep_stmt->executeQuery(); res->next(); new_session_id = res->getInt("id"); } else { prep_stmt = con->prepareStatement("INSERT INTO practice_sessions (description, seconds, practice_category_id) VALUES (?, ?, ?) RETURNING id"); string description = request_body["description"].s(); int seconds = request_body["seconds"].i(); int practice_category_id = request_body["practice_category_id"].i(); prep_stmt->setString(1, description); prep_stmt->setInt(2, seconds); prep_stmt->setInt(3, practice_category_id); ResultSet *res = prep_stmt->executeQuery(); res->next(); new_session_id = res->getInt("id"); } if(request_body.has("songs")){ for(const auto& song : request_body["songs"]){ prep_stmt = con->prepareStatement("INSERT INTO songs_practiced (practice_session_id, song_id) VALUES (?, ?)"); prep_stmt->setInt(1, new_session_id); prep_stmt->setInt(2, int(song["id"])); prep_stmt->execute(); } } status = {{"status", "success"}}; return status; }); CROW_ROUTE(app, "/songs")([](){ connect(); crow::json::wvalue entries; ResultSet *res = stmt->executeQuery("SELECT * FROM songs WHERE learned=True ORDER BY title ASC;"); int i = 0; while (res->next()) { int id = res->getInt("id"); string title = res->getString("title"); string notes = res->getString("notes"); entries[i] = {{"id", id}, {"title", title}, {"notes", notes}}; i++; } delete res; return entries; }); CROW_ROUTE(app, "/instruments")([](){ connect(); crow::json::wvalue entries; ResultSet *res = stmt->executeQuery("SELECT * FROM instruments"); int i = 0; while (res->next()) { int id = res->getInt("id"); string instrument = res->getString("name"); entries[i] = {{"id", id}, {"name", instrument}}; i++; } delete res; return entries; }); CROW_ROUTE(app, "/categories")([](){ connect(); crow::json::wvalue entries; ResultSet *res = stmt->executeQuery("SELECT practice_categories.id, practice_categories.name AS category, instruments.name AS instrument FROM practice_categories JOIN instruments ON practice_categories.instrument_id = instruments.id ORDER BY practice_categories.id ASC"); int i = 0; while (res->next()) { int id = res->getInt("id"); string category = res->getString("category"); string instrument = res->getString("instrument"); entries[i] = {{"id", id}, {"category", category}, {"instrument", instrument}}; i++; } delete res; return entries; }); CROW_ROUTE(app, "/summary")([](){ connect(); crow::json::wvalue entries; ResultSet *res = stmt->executeQuery("SELECT * FROM summary ORDER BY chunks_practiced ASC;"); int i = 0; while (res->next()) { int category_id = res->getInt("category_id"); string category = res->getString("category"); string instrument = res->getString("instrument"); double chunks_practiced = res->getDouble("chunks_practiced"); int weight = res->getInt("weight"); entries[i] = {{"category_id", category_id}, {"category", category}, {"instrument", instrument}, {"chunks_practiced", chunks_practiced}, {"weight", weight}}; i++; } delete res; return entries; }); CROW_ROUTE(app, "/status")([](){ connect(); crow::json::wvalue entries; ResultSet *res = stmt->executeQuery("SELECT * FROM practice_status;"); res->next(); int practiced = res->getInt("seconds_practiced_today"); int left = res->getInt("seconds_left"); int to_get_ahead = res->getInt("seconds_left_to_get_ahead"); entries = {{"seconds_practiced", practiced}, {"seconds_left_to_practice_today", left}, {"seconds_left_to_get_ahead", to_get_ahead}}; delete res; return entries; }); CROW_ROUTE(app, "/show-category/")([](int category_id){ connect(); crow::json::wvalue entries; prep_stmt = con->prepareStatement("SELECT practice_sessions.id, practice_sessions.description, seconds, songs.id AS song_id, songs.title, comments, created_at, practice_categories.name AS category, instruments.name AS instrument " "FROM practice_sessions JOIN practice_categories ON practice_category_id = practice_categories.id " "JOIN instruments ON instrument_id = instruments.id " "LEFT JOIN songs_practiced ON practice_sessions.id = songs_practiced.practice_session_id " "LEFT JOIN songs ON songs_practiced.song_id = songs.id WHERE practice_category_id = ? ORDER BY practice_sessions.id DESC;"); prep_stmt->setInt(1, category_id); ResultSet *res = prep_stmt->executeQuery(); int i = -1; int previous_session_id = 0; int current_song_index; while (res->next()) { int id = res->getInt("id"); string description = res->getString("description"); int seconds = res->getInt("seconds"); string comments = res->getString("comments"); string created_at = res->getString("created_at"); string category = res->getString("category"); string instrument = res->getString("instrument"); int song_id = res->getInt("song_id"); string song_title = res->getString("title"); if(id != previous_session_id){ i++; previous_session_id = id; current_song_index = 0; crow::json::wvalue songs = crow::json::wvalue::list(); if(song_id != 0){ songs[current_song_index] = { {"id", song_id}, {"title", song_title} }; } entries[i] = { {"id", id}, {"description", description}, {"seconds", seconds}, {"comments", comments}, {"created_at", created_at}, {"category", category}, {"instrument", instrument}, {"songs", songs} }; current_song_index++; } else { entries[i]["songs"][current_song_index] = { {"id", song_id}, {"title", song_title} }; current_song_index++; } } delete res; return entries; }); app.port(18080).run(); atexit(exiting); }