From 74a2da5f6fcb298df6c1bb911f457d0728104a22 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sun, 7 Jan 2024 21:28:56 +0100 Subject: [PATCH] Added postfix to sql statements, implemented stats ~1.75h work --- MonsterTradingCards.sh | 333 ++++++++++++++++++ src/at/nanopenguin/mtcg/application/User.java | 32 ++ .../mtcg/application/service/GameService.java | 39 +- .../application/service/TradingService.java | 1 - .../mtcg/application/service/UserService.java | 1 + .../application/service/schemas/Card.java | 8 +- .../service/schemas/TradingDeal.java | 9 +- .../service/schemas/UserCredentials.java | 6 +- .../application/service/schemas/UserData.java | 8 +- .../service/schemas/UserStats.java | 9 +- src/at/nanopenguin/mtcg/db/DbQuery.java | 21 +- .../nanopenguin/mtcg/http/RequestHandler.java | 1 + 12 files changed, 438 insertions(+), 30 deletions(-) create mode 100644 MonsterTradingCards.sh diff --git a/MonsterTradingCards.sh b/MonsterTradingCards.sh new file mode 100644 index 0000000..04ba751 --- /dev/null +++ b/MonsterTradingCards.sh @@ -0,0 +1,333 @@ +#!/bin/sh + +# -------------------------------------------------- +# Monster Trading Cards Game +# -------------------------------------------------- +echo "CURL Testing for Monster Trading Cards Game" +echo . + +# -------------------------------------------------- +echo "1) Create Users (Registration)" +# Create User +curl -i -X POST http://localhost:10001/users --header "Content-Type: application/json" -d "{\"Username\":\"kienboec\", \"Password\":\"daniel\"}" +echo . +curl -i -X POST http://localhost:10001/users --header "Content-Type: application/json" -d "{\"Username\":\"altenhof\", \"Password\":\"markus\"}" +echo . +curl -i -X POST http://localhost:10001/users --header "Content-Type: application/json" -d "{\"Username\":\"admin\", \"Password\":\"istrator\"}" +echo . + +read -p "Press any key to resume ..." null + +echo "should fail:" +curl -i -X POST http://localhost:10001/users --header "Content-Type: application/json" -d "{\"Username\":\"kienboec\", \"Password\":\"daniel\"}" +echo . +curl -i -X POST http://localhost:10001/users --header "Content-Type: application/json" -d "{\"Username\":\"kienboec\", \"Password\":\"different\"}" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "2) Login Users" +token1=$(curl -i -X POST http://localhost:10001/sessions --header "Content-Type: application/json" -d "{\"Username\":\"kienboec\", \"Password\":\"daniel\"}") +echo . +token2=$(curl -i -X POST http://localhost:10001/sessions --header "Content-Type: application/json" -d "{\"Username\":\"altenhof\", \"Password\":\"markus\"}") +echo . +token3=$(curl -i -X POST http://localhost:10001/sessions --header "Content-Type: application/json" -d "{\"Username\":\"admin\", \"Password\":\"istrator\"}") +echo . + +read -p "Press any key to resume ..." null + +echo "should fail:" +curl -i -X POST http://localhost:10001/sessions --header "Content-Type: application/json" -d "{\"Username\":\"kienboec\", \"Password\":\"different\"}" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "3) create packages (done by admin)" +curl -i -X POST http://localhost:10001/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token3" -d "[{\"Id\":\"845f0dc7-37d0-426e-994e-43fc3ac83c08\", \"Name\":\"WaterGoblin\", \"Damage\": 10.0}, {\"Id\":\"99f8f8dc-e25e-4a95-aa2c-782823f36e2a\", \"Name\":\"Dragon\", \"Damage\": 50.0}, {\"Id\":\"e85e3976-7c86-4d06-9a80-641c2019a79f\", \"Name\":\"WaterSpell\", \"Damage\": 20.0}, {\"Id\":\"1cb6ab86-bdb2-47e5-b6e4-68c5ab389334\", \"Name\":\"Ork\", \"Damage\": 45.0}, {\"Id\":\"dfdd758f-649c-40f9-ba3a-8657f4b3439f\", \"Name\":\"FireSpell\", \"Damage\": 25.0}]" +echo . +curl -i -X POST http://localhost:10001/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token3" -d "[{\"Id\":\"644808c2-f87a-4600-b313-122b02322fd5\", \"Name\":\"WaterGoblin\", \"Damage\": 9.0}, {\"Id\":\"4a2757d6-b1c3-47ac-b9a3-91deab093531\", \"Name\":\"Dragon\", \"Damage\": 55.0}, {\"Id\":\"91a6471b-1426-43f6-ad65-6fc473e16f9f\", \"Name\":\"WaterSpell\", \"Damage\": 21.0}, {\"Id\":\"4ec8b269-0dfa-4f97-809a-2c63fe2a0025\", \"Name\":\"Ork\", \"Damage\": 55.0}, {\"Id\":\"f8043c23-1534-4487-b66b-238e0c3c39b5\", \"Name\":\"WaterSpell\", \"Damage\": 23.0}]" +echo . +curl -i -X POST http://localhost:10001/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token3" -d "[{\"Id\":\"b017ee50-1c14-44e2-bfd6-2c0c5653a37c\", \"Name\":\"WaterGoblin\", \"Damage\": 11.0}, {\"Id\":\"d04b736a-e874-4137-b191-638e0ff3b4e7\", \"Name\":\"Dragon\", \"Damage\": 70.0}, {\"Id\":\"88221cfe-1f84-41b9-8152-8e36c6a354de\", \"Name\":\"WaterSpell\", \"Damage\": 22.0}, {\"Id\":\"1d3f175b-c067-4359-989d-96562bfa382c\", \"Name\":\"Ork\", \"Damage\": 40.0}, {\"Id\":\"171f6076-4eb5-4a7d-b3f2-2d650cc3d237\", \"Name\":\"RegularSpell\", \"Damage\": 28.0}]" +echo . +curl -i -X POST http://localhost:10001/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token3" -d "[{\"Id\":\"ed1dc1bc-f0aa-4a0c-8d43-1402189b33c8\", \"Name\":\"WaterGoblin\", \"Damage\": 10.0}, {\"Id\":\"65ff5f23-1e70-4b79-b3bd-f6eb679dd3b5\", \"Name\":\"Dragon\", \"Damage\": 50.0}, {\"Id\":\"55ef46c4-016c-4168-bc43-6b9b1e86414f\", \"Name\":\"WaterSpell\", \"Damage\": 20.0}, {\"Id\":\"f3fad0f2-a1af-45df-b80d-2e48825773d9\", \"Name\":\"Ork\", \"Damage\": 45.0}, {\"Id\":\"8c20639d-6400-4534-bd0f-ae563f11f57a\", \"Name\":\"WaterSpell\", \"Damage\": 25.0}]" +echo . +curl -i -X POST http://localhost:10001/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token3" -d "[{\"Id\":\"d7d0cb94-2cbf-4f97-8ccf-9933dc5354b8\", \"Name\":\"WaterGoblin\", \"Damage\": 9.0}, {\"Id\":\"44c82fbc-ef6d-44ab-8c7a-9fb19a0e7c6e\", \"Name\":\"Dragon\", \"Damage\": 55.0}, {\"Id\":\"2c98cd06-518b-464c-b911-8d787216cddd\", \"Name\":\"WaterSpell\", \"Damage\": 21.0}, {\"Id\":\"951e886a-0fbf-425d-8df5-af2ee4830d85\", \"Name\":\"Ork\", \"Damage\": 55.0}, {\"Id\":\"dcd93250-25a7-4dca-85da-cad2789f7198\", \"Name\":\"FireSpell\", \"Damage\": 23.0}]" +echo . +curl -i -X POST http://localhost:10001/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token3" -d "[{\"Id\":\"b2237eca-0271-43bd-87f6-b22f70d42ca4\", \"Name\":\"WaterGoblin\", \"Damage\": 11.0}, {\"Id\":\"9e8238a4-8a7a-487f-9f7d-a8c97899eb48\", \"Name\":\"Dragon\", \"Damage\": 70.0}, {\"Id\":\"d60e23cf-2238-4d49-844f-c7589ee5342e\", \"Name\":\"WaterSpell\", \"Damage\": 22.0}, {\"Id\":\"fc305a7a-36f7-4d30-ad27-462ca0445649\", \"Name\":\"Ork\", \"Damage\": 40.0}, {\"Id\":\"84d276ee-21ec-4171-a509-c1b88162831c\", \"Name\":\"RegularSpell\", \"Damage\": 28.0}]" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "4) acquire packages kienboec" +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "" +echo . +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "" +echo . +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "" +echo . +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "" +echo . +echo "should fail (no money):" +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "5) acquire packages altenhof" +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "" +echo . +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "" +echo . +echo "should fail (no package):" +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "6) add new packages" +curl -i -X POST http://localhost:10001/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token3" -d "[{\"Id\":\"67f9048f-99b8-4ae4-b866-d8008d00c53d\", \"Name\":\"WaterGoblin\", \"Damage\": 10.0}, {\"Id\":\"aa9999a0-734c-49c6-8f4a-651864b14e62\", \"Name\":\"RegularSpell\", \"Damage\": 50.0}, {\"Id\":\"d6e9c720-9b5a-40c7-a6b2-bc34752e3463\", \"Name\":\"Knight\", \"Damage\": 20.0}, {\"Id\":\"02a9c76e-b17d-427f-9240-2dd49b0d3bfd\", \"Name\":\"RegularSpell\", \"Damage\": 45.0}, {\"Id\":\"2508bf5c-20d7-43b4-8c77-bc677decadef\", \"Name\":\"FireElf\", \"Damage\": 25.0}]" +echo . +curl -i -X POST http://localhost:10001/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token3" -d "[{\"Id\":\"70962948-2bf7-44a9-9ded-8c68eeac7793\", \"Name\":\"WaterGoblin\", \"Damage\": 9.0}, {\"Id\":\"74635fae-8ad3-4295-9139-320ab89c2844\", \"Name\":\"FireSpell\", \"Damage\": 55.0}, {\"Id\":\"ce6bcaee-47e1-4011-a49e-5a4d7d4245f3\", \"Name\":\"Knight\", \"Damage\": 21.0}, {\"Id\":\"a6fde738-c65a-4b10-b400-6fef0fdb28ba\", \"Name\":\"FireSpell\", \"Damage\": 55.0}, {\"Id\":\"a1618f1e-4f4c-4e09-9647-87e16f1edd2d\", \"Name\":\"FireElf\", \"Damage\": 23.0}]" +echo . +curl -i -X POST http://localhost:10001/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token3" -d "[{\"Id\":\"2272ba48-6662-404d-a9a1-41a9bed316d9\", \"Name\":\"WaterGoblin\", \"Damage\": 11.0}, {\"Id\":\"3871d45b-b630-4a0d-8bc6-a5fc56b6a043\", \"Name\":\"Dragon\", \"Damage\": 70.0}, {\"Id\":\"166c1fd5-4dcb-41a8-91cb-f45dcd57cef3\", \"Name\":\"Knight\", \"Damage\": 22.0}, {\"Id\":\"237dbaef-49e3-4c23-b64b-abf5c087b276\", \"Name\":\"WaterSpell\", \"Damage\": 40.0}, {\"Id\":\"27051a20-8580-43ff-a473-e986b52f297a\", \"Name\":\"FireElf\", \"Damage\": 28.0}]" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "7) acquire newly created packages altenhof" +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "" +echo . +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "" +echo . +echo "should fail (no money):" +curl -i -X POST http://localhost:10001/transactions/packages --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "8) show all acquired cards kienboec" +curl -i -X GET http://localhost:10001/cards --header "Authorization: Bearer $token1" +echo "should fail (no token)" +curl -i -X GET http://localhost:10001/cards +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "9) show all acquired cards altenhof" +curl -i -X GET http://localhost:10001/cards --header "Authorization: Bearer $token2" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "10) show unconfigured deck" +curl -i -X GET http://localhost:10001/deck --header "Authorization: Bearer $token1" +echo . +curl -i -X GET http://localhost:10001/deck --header "Authorization: Bearer $token2" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "11) configure deck" +curl -i -X PUT http://localhost:10001/deck --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "[\"845f0dc7-37d0-426e-994e-43fc3ac83c08\", \"99f8f8dc-e25e-4a95-aa2c-782823f36e2a\", \"e85e3976-7c86-4d06-9a80-641c2019a79f\", \"171f6076-4eb5-4a7d-b3f2-2d650cc3d237\"]" +echo . +curl -i -X GET http://localhost:10001/deck --header "Authorization: Bearer $token1" +echo . +curl -i -X PUT http://localhost:10001/deck --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "[\"aa9999a0-734c-49c6-8f4a-651864b14e62\", \"d6e9c720-9b5a-40c7-a6b2-bc34752e3463\", \"d60e23cf-2238-4d49-844f-c7589ee5342e\", \"02a9c76e-b17d-427f-9240-2dd49b0d3bfd\"]" +echo . +curl -i -X GET http://localhost:10001/deck --header "Authorization: Bearer $token2" +echo . +echo . + +read -p "Press any key to resume ..." null + +echo "should fail and show original from before:" +curl -i -X PUT http://localhost:10001/deck --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "[\"845f0dc7-37d0-426e-994e-43fc3ac83c08\", \"99f8f8dc-e25e-4a95-aa2c-782823f36e2a\", \"e85e3976-7c86-4d06-9a80-641c2019a79f\", \"171f6076-4eb5-4a7d-b3f2-2d650cc3d237\"]" +echo . +curl -i -X GET http://localhost:10001/deck --header "Authorization: Bearer $token2" +echo . +echo . +echo "should fail ... only 3 cards set" +curl -i -X PUT http://localhost:10001/deck --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "[\"aa9999a0-734c-49c6-8f4a-651864b14e62\", \"d6e9c720-9b5a-40c7-a6b2-bc34752e3463\", \"d60e23cf-2238-4d49-844f-c7589ee5342e\"]" +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "12) show configured deck" +curl -i -X GET http://localhost:10001/deck --header "Authorization: Bearer $token1" +echo . +curl -i -X GET http://localhost:10001/deck --header "Authorization: Bearer $token2" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "13) show configured deck different representation" +echo "kienboec" +curl -i -X GET http://localhost:10001/deck?format=plain --header "Authorization: Bearer $token1" +echo . +echo . +echo "altenhof" +curl -i -X GET http://localhost:10001/deck?format=plain --header "Authorization: Bearer $token2" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "14) edit user data" +echo . +curl -i -X GET http://localhost:10001/users/kienboec --header "Authorization: Bearer $token1" +echo . +curl -i -X GET http://localhost:10001/users/altenhof --header "Authorization: Bearer $token2" +echo . +curl -i -X PUT http://localhost:10001/users/kienboec --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "{\"Name\": \"Kienboeck\", \"Bio\": \"me playin...\", \"Image\": \":-)\"}" +echo . +curl -i -X PUT http://localhost:10001/users/altenhof --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "{\"Name\": \"Altenhofer\", \"Bio\": \"me codin...\", \"Image\": \":-D\"}" +echo . +curl -i -X GET http://localhost:10001/users/kienboec --header "Authorization: Bearer $token1" +echo . +curl -i -X GET http://localhost:10001/users/altenhof --header "Authorization: Bearer $token2" +echo . +echo . + +read -p "Press any key to resume ..." null + +echo "should fail:" +curl -i -X GET http://localhost:10001/users/altenhof --header "Authorization: Bearer $token1" +echo . +curl -i -X GET http://localhost:10001/users/kienboec --header "Authorization: Bearer $token2" +echo . +curl -i -X PUT http://localhost:10001/users/kienboec --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "{\"Name\": \"Hoax\", \"Bio\": \"me playin...\", \"Image\": \":-)\"}" +echo . +curl -i -X PUT http://localhost:10001/users/altenhof --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "{\"Name\": \"Hoax\", \"Bio\": \"me codin...\", \"Image\": \":-D\"}" +echo . +curl -i -X GET http://localhost:10001/users/someGuy --header "Authorization: Bearer $token1" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "15) stats" +curl -i -X GET http://localhost:10001/stats --header "Authorization: Bearer $token1" +echo . +curl -i -X GET http://localhost:10001/stats --header "Authorization: Bearer $token2" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "16) scoreboard" +curl -i -X GET http://localhost:10001/scoreboard --header "Authorization: Bearer $token1" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "17) battle" +curl -i -X POST http://localhost:10001/battles --header "Authorization: Bearer $token1" & +curl -i -X POST http://localhost:10001/battles --header "Authorization: Bearer $token2" & +wait + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "18) Stats" +echo "kienboec" +curl -i -X GET http://localhost:10001/stats --header "Authorization: Bearer $token1" +echo . +echo "altenhof" +curl -i -X GET http://localhost:10001/stats --header "Authorization: Bearer $token2" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "19) scoreboard" +curl -i -X GET http://localhost:10001/scoreboard --header "Authorization: Bearer $token1" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "20) trade" +echo "check trading deals" +curl -i -X GET http://localhost:10001/tradings --header "Authorization: Bearer $token1" +echo . +echo "create trading deal" +curl -i -X POST http://localhost:10001/tradings --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "{\"Id\": \"6cd85277-4590-49d4-b0cf-ba0a921faad0\", \"CardToTrade\": \"1cb6ab86-bdb2-47e5-b6e4-68c5ab389334\", \"Type\": \"monster\", \"MinimumDamage\": 15}" +echo . + +read -p "Press any key to resume ..." null + +echo "check trading deals" +curl -i -X GET http://localhost:10001/tradings --header "Authorization: Bearer $token1" +echo . +curl -i -X GET http://localhost:10001/tradings --header "Authorization: Bearer $token2" +echo . + +read -p "Press any key to resume ..." null + +echo "delete trading deals" +curl -i -X DELETE http://localhost:10001/tradings/6cd85277-4590-49d4-b0cf-ba0a921faad0 --header "Authorization: Bearer $token1" +echo . +echo . + +read -p "Press any key to resume ..." null + +# -------------------------------------------------- +echo "21) check trading deals" +curl -i -X GET http://localhost:10001/tradings --header "Authorization: Bearer $token1" +echo . +curl -i -X POST http://localhost:10001/tradings --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "{\"Id\": \"6cd85277-4590-49d4-b0cf-ba0a921faad0\", \"CardToTrade\": \"1cb6ab86-bdb2-47e5-b6e4-68c5ab389334\", \"Type\": \"monster\", \"MinimumDamage\": 15}" +echo "check trading deals" +curl -i -X GET http://localhost:10001/tradings --header "Authorization: Bearer $token1" +echo . +curl -i -X GET http://localhost:10001/tradings --header "Authorization: Bearer $token2" +echo . + +read -p "Press any key to resume ..." null + +echo "try to trade with yourself (should fail)" +curl -i -X POST http://localhost:10001/tradings/6cd85277-4590-49d4-b0cf-ba0a921faad0 --header "Content-Type: application/json" --header "Authorization: Bearer $token1" -d "\"4ec8b269-0dfa-4f97-809a-2c63fe2a0025\"" +echo . + +read -p "Press any key to resume ..." null + +echo "try to trade" +echo . +curl -i -X POST http://localhost:10001/tradings/6cd85277-4590-49d4-b0cf-ba0a921faad0 --header "Content-Type: application/json" --header "Authorization: Bearer $token2" -d "\"951e886a-0fbf-425d-8df5-af2ee4830d85\"" +echo . +curl -i -X GET http://localhost:10001/tradings --header "Authorization: Bearer $token1" +echo . +curl -i -X GET http://localhost:10001/tradings --header "Authorization: Bearer $token2" +echo . + +# -------------------------------------------------- +echo "end..." \ No newline at end of file diff --git a/src/at/nanopenguin/mtcg/application/User.java b/src/at/nanopenguin/mtcg/application/User.java index 8c77a62..5f81969 100644 --- a/src/at/nanopenguin/mtcg/application/User.java +++ b/src/at/nanopenguin/mtcg/application/User.java @@ -1,15 +1,20 @@ package at.nanopenguin.mtcg.application; +import at.nanopenguin.mtcg.application.service.schemas.TradingDeal; import at.nanopenguin.mtcg.application.service.schemas.UserCredentials; import at.nanopenguin.mtcg.application.service.schemas.UserData; +import at.nanopenguin.mtcg.application.service.schemas.UserStats; import at.nanopenguin.mtcg.db.DbQuery; import at.nanopenguin.mtcg.db.SqlCommand; import at.nanopenguin.mtcg.db.Table; import at.nanopenguin.mtcg.http.HttpStatus; import at.nanopenguin.mtcg.http.Response; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.val; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.UUID; public class User { public static boolean create(UserCredentials userCredentials) throws SQLException { @@ -43,4 +48,31 @@ public class User { val row1 = result.get(0); return new UserData((String) row1.get("name"), (String) row1.get("bio"), (String) row1.get("image")); } + + public static UserStats getStats(UUID userUuid) throws SQLException { + return new ObjectMapper().convertValue(DbQuery.builder() + .command(SqlCommand.SELECT) + .table(Table.USERS) + .condition("uuid", userUuid) + .executeQuery() + .get(0), + UserStats.class); + } + + public static UserStats[] scoreboard() throws SQLException { + val dbQueryBuilder = DbQuery.builder() + .command(SqlCommand.SELECT) + .table(Table.USERS) + .column("name") + .column("elo") + .column("wins") + .column("losses") + .postfix(" ORDER BY elo"); + + ArrayList stats = new ArrayList<>(); + for (val row : dbQueryBuilder.executeQuery()) { + stats.add(new ObjectMapper().convertValue(row, UserStats.class)); + } + return stats.toArray(new UserStats[0]); + } } \ No newline at end of file diff --git a/src/at/nanopenguin/mtcg/application/service/GameService.java b/src/at/nanopenguin/mtcg/application/service/GameService.java index 9d94411..0b3cff1 100644 --- a/src/at/nanopenguin/mtcg/application/service/GameService.java +++ b/src/at/nanopenguin/mtcg/application/service/GameService.java @@ -1,31 +1,40 @@ package at.nanopenguin.mtcg.application.service; +import at.nanopenguin.mtcg.application.SessionHandler; +import at.nanopenguin.mtcg.application.TokenValidity; +import at.nanopenguin.mtcg.application.User; import at.nanopenguin.mtcg.http.HttpMethod; import at.nanopenguin.mtcg.http.HttpRequest; import at.nanopenguin.mtcg.http.HttpStatus; import at.nanopenguin.mtcg.http.Response; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.sql.SQLException; +import java.util.UUID; public class GameService implements Service { @Override - public Response handleRequest(HttpRequest request) throws JsonProcessingException { - try { - if (request.getPath().split("/")[1].equals("stats") && request.getMethod() == HttpMethod.GET) { - return new Response(HttpStatus.NOT_IMPLEMENTED); - } + public Response handleRequest(HttpRequest request) throws JsonProcessingException, SQLException { - if (request.getPath().split("/")[1].equals("scoreboard") && request.getMethod() == HttpMethod.GET) { - return new Response(HttpStatus.NOT_IMPLEMENTED); - } + UUID authToken = SessionHandler.tokenFromHttpHeader(request.getHttpHeader("Authorization")); + if (SessionHandler.getInstance().verifyUUID(authToken) != TokenValidity.VALID) + return new Response(HttpStatus.UNAUTHORIZED); + UUID userUuid = SessionHandler.getInstance().userUuidFromToken(authToken); - if (request.getPath().split("/")[1].equals("battles") && request.getMethod() == HttpMethod.POST) { - return new Response(HttpStatus.NOT_IMPLEMENTED); - } - - return new Response(HttpStatus.NOT_FOUND); - } catch (ArrayIndexOutOfBoundsException e) { - return new Response(HttpStatus.BAD_REQUEST); + if (request.getPath().split("/")[1].equals("stats") && request.getMethod() == HttpMethod.GET) { + return new Response(HttpStatus.OK, new ObjectMapper().writeValueAsString(User.getStats(userUuid))); } + + if (request.getPath().split("/")[1].equals("scoreboard") && request.getMethod() == HttpMethod.GET) { + return new Response(HttpStatus.OK, new ObjectMapper().writeValueAsString(User.scoreboard())); + } + + if (request.getPath().split("/")[1].equals("battles") && request.getMethod() == HttpMethod.POST) { + return new Response(HttpStatus.NOT_IMPLEMENTED); + } + + return new Response(HttpStatus.NOT_FOUND); } } diff --git a/src/at/nanopenguin/mtcg/application/service/TradingService.java b/src/at/nanopenguin/mtcg/application/service/TradingService.java index 9bfa56f..af7b940 100644 --- a/src/at/nanopenguin/mtcg/application/service/TradingService.java +++ b/src/at/nanopenguin/mtcg/application/service/TradingService.java @@ -4,7 +4,6 @@ import at.nanopenguin.mtcg.application.SessionHandler; import at.nanopenguin.mtcg.application.TokenValidity; import at.nanopenguin.mtcg.application.Trade; import at.nanopenguin.mtcg.application.service.schemas.TradingDeal; -import at.nanopenguin.mtcg.http.HttpMethod; import at.nanopenguin.mtcg.http.HttpRequest; import at.nanopenguin.mtcg.http.HttpStatus; import at.nanopenguin.mtcg.http.Response; diff --git a/src/at/nanopenguin/mtcg/application/service/UserService.java b/src/at/nanopenguin/mtcg/application/service/UserService.java index cf2f390..2ac54f9 100644 --- a/src/at/nanopenguin/mtcg/application/service/UserService.java +++ b/src/at/nanopenguin/mtcg/application/service/UserService.java @@ -11,6 +11,7 @@ import at.nanopenguin.mtcg.http.HttpStatus; import at.nanopenguin.mtcg.http.Response; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; import lombok.val; import java.sql.SQLException; diff --git a/src/at/nanopenguin/mtcg/application/service/schemas/Card.java b/src/at/nanopenguin/mtcg/application/service/schemas/Card.java index ff93860..528b4e4 100644 --- a/src/at/nanopenguin/mtcg/application/service/schemas/Card.java +++ b/src/at/nanopenguin/mtcg/application/service/schemas/Card.java @@ -1,10 +1,14 @@ package at.nanopenguin.mtcg.application.service.schemas; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; import java.util.UUID; +@JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) @JsonIgnoreProperties(ignoreUnknown = true) -public record Card(@JsonProperty("id") UUID id, String name, Float damage) { +public record Card( + UUID id, + String name, + Float damage) { } diff --git a/src/at/nanopenguin/mtcg/application/service/schemas/TradingDeal.java b/src/at/nanopenguin/mtcg/application/service/schemas/TradingDeal.java index 3cc89fd..f19f9c7 100644 --- a/src/at/nanopenguin/mtcg/application/service/schemas/TradingDeal.java +++ b/src/at/nanopenguin/mtcg/application/service/schemas/TradingDeal.java @@ -1,7 +1,14 @@ package at.nanopenguin.mtcg.application.service.schemas; +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +@JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) @JsonIgnoreProperties(ignoreUnknown = true) -public record TradingDeal(String id, String cardToTrade, String type, Float minimumDamage) { +public record TradingDeal( + String id, + String cardToTrade, + String type, + Float minimumDamage) { } diff --git a/src/at/nanopenguin/mtcg/application/service/schemas/UserCredentials.java b/src/at/nanopenguin/mtcg/application/service/schemas/UserCredentials.java index dc1cb40..e0f3138 100644 --- a/src/at/nanopenguin/mtcg/application/service/schemas/UserCredentials.java +++ b/src/at/nanopenguin/mtcg/application/service/schemas/UserCredentials.java @@ -1,7 +1,11 @@ package at.nanopenguin.mtcg.application.service.schemas; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +@JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) @JsonIgnoreProperties(ignoreUnknown = true) -public record UserCredentials(String username, String password) { +public record UserCredentials( + String username, + String password) { } diff --git a/src/at/nanopenguin/mtcg/application/service/schemas/UserData.java b/src/at/nanopenguin/mtcg/application/service/schemas/UserData.java index bd1d332..13d2428 100644 --- a/src/at/nanopenguin/mtcg/application/service/schemas/UserData.java +++ b/src/at/nanopenguin/mtcg/application/service/schemas/UserData.java @@ -1,7 +1,13 @@ package at.nanopenguin.mtcg.application.service.schemas; +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +@JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) @JsonIgnoreProperties(ignoreUnknown = true) -public record UserData(String name, String bio, String image) { +public record UserData( + String name, + String bio, + String image) { } diff --git a/src/at/nanopenguin/mtcg/application/service/schemas/UserStats.java b/src/at/nanopenguin/mtcg/application/service/schemas/UserStats.java index 5863e66..428c7af 100644 --- a/src/at/nanopenguin/mtcg/application/service/schemas/UserStats.java +++ b/src/at/nanopenguin/mtcg/application/service/schemas/UserStats.java @@ -1,7 +1,14 @@ package at.nanopenguin.mtcg.application.service.schemas; +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +@JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) @JsonIgnoreProperties(ignoreUnknown = true) -public record UserStats(String name, Integer elo, Integer wins, Integer losses) { +public record UserStats( + String name, + Integer elo, + Integer wins, + Integer losses) { } diff --git a/src/at/nanopenguin/mtcg/db/DbQuery.java b/src/at/nanopenguin/mtcg/db/DbQuery.java index f98bb9b..ff56db1 100644 --- a/src/at/nanopenguin/mtcg/db/DbQuery.java +++ b/src/at/nanopenguin/mtcg/db/DbQuery.java @@ -30,6 +30,7 @@ public final class DbQuery { @Singular private List values; private boolean isScript; + private String postfix = null; public static class DbQueryBuilder { @@ -194,11 +195,12 @@ public final class DbQuery { .filter(columnName -> columnName.matches("^[a-zA-Z0-9_]+( AS [a-zA-Z0-9_]+)?$")) .collect(Collectors.joining(", ")); - return String.format("INSERT INTO %s (%s) VALUES (%s) ON CONFLICT DO NOTHING%s;", + return String.format("INSERT INTO %s (%s) VALUES (%s) ON CONFLICT DO NOTHING%s%s;", table.table, columns, String.join(", ", Collections.nCopies(this.parameters.size(), "?")), - hasReturn ? " RETURNING " + this.returnColumn : ""); + hasReturn ? " RETURNING " + this.returnColumn : "", + this.postfix != null ? " " + this.postfix : ""); } private int create() throws SQLException { @@ -219,10 +221,11 @@ public final class DbQuery { } this.columns.forEach(columnJoiner::add); - String sql = String.format("SELECT %s FROM %s%s;", + String sql = String.format("SELECT %s FROM %s%s%s;", columnJoiner, table.table, - this.conditions.isEmpty() ? "" : " WHERE " + this.buildParameterizedString(this.conditions, " AND ")); + this.conditions.isEmpty() ? "" : " WHERE " + this.buildParameterizedString(this.conditions, " AND "), + this.postfix != null ? " " + this.postfix : ""); return executeQuery(sql, new ArrayList<>(this.conditions.values())); } @@ -231,11 +234,12 @@ public final class DbQuery { if (this.parameters.isEmpty()) throw new SQLException(); if (this.conditions.isEmpty()) throw new SQLException(); - return String.format("UPDATE %s SET %s WHERE %s%s;", + return String.format("UPDATE %s SET %s WHERE %s%s%s;", table.table, this.buildParameterizedString(this.parameters, ", "), this.buildParameterizedString(this.conditions, " AND "), - hasReturn ? " RETURNING " + this.returnColumn : ""); + hasReturn ? " RETURNING " + this.returnColumn : "", + this.postfix != null ? " " + this.postfix : ""); } private int update() throws SQLException { @@ -260,9 +264,10 @@ public final class DbQuery { private int delete() throws SQLException { if (this.conditions.isEmpty()) throw new SQLException(); - String sql = String.format("DELETE FROM %s WHERE %s;", + String sql = String.format("DELETE FROM %s WHERE %s%s;", table.table, - this.buildParameterizedString(this.conditions, " AND ")); + this.buildParameterizedString(this.conditions, " AND "), + this.postfix != null ? " " + this.postfix : ""); return executeUpdate(sql, new ArrayList<>(this.conditions.values())); } diff --git a/src/at/nanopenguin/mtcg/http/RequestHandler.java b/src/at/nanopenguin/mtcg/http/RequestHandler.java index 53160a1..59504be 100644 --- a/src/at/nanopenguin/mtcg/http/RequestHandler.java +++ b/src/at/nanopenguin/mtcg/http/RequestHandler.java @@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor; import java.io.*; import java.net.Socket; +import java.sql.SQLException; import java.util.Arrays; @RequiredArgsConstructor