added crits

~30 min of work
This commit is contained in:
Benedikt Galbavy 2024-01-22 01:12:10 +01:00
parent bfde39a595
commit 9ffc92f1a6
8 changed files with 30 additions and 15 deletions

View File

@ -47,17 +47,17 @@ read -p "Press any key to resume ..." null
# -------------------------------------------------- # --------------------------------------------------
echo "3) create packages (done by admin)" 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}]" 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, \"Crit\":30}, {\"Id\":\"99f8f8dc-e25e-4a95-aa2c-782823f36e2a\", \"Name\":\"Dragon\", \"Damage\": 50.0, \"Crit\":10}, {\"Id\":\"e85e3976-7c86-4d06-9a80-641c2019a79f\", \"Name\":\"WaterSpell\", \"Damage\": 20.0, \"Crit\":null}, {\"Id\":\"1cb6ab86-bdb2-47e5-b6e4-68c5ab389334\", \"Name\":\"Ork\", \"Damage\": 45.0, \"Crit\":0}, {\"Id\":\"dfdd758f-649c-40f9-ba3a-8657f4b3439f\", \"Name\":\"FireSpell\", \"Damage\": 25.0, \"Crit\":null}]"
echo . 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}]" 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, \"Crit\":15}, {\"Id\":\"4a2757d6-b1c3-47ac-b9a3-91deab093531\", \"Name\":\"Dragon\", \"Damage\": 55.0, \"Crit\":15}, {\"Id\":\"91a6471b-1426-43f6-ad65-6fc473e16f9f\", \"Name\":\"WaterSpell\", \"Damage\": 21.0, \"Crit\":null}, {\"Id\":\"4ec8b269-0dfa-4f97-809a-2c63fe2a0025\", \"Name\":\"Ork\", \"Damage\": 55.0, \"Crit\":5}, {\"Id\":\"f8043c23-1534-4487-b66b-238e0c3c39b5\", \"Name\":\"WaterSpell\", \"Damage\": 23.0, \"Crit\":null}]"
echo . 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}]" 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, \"Crit\":45}, {\"Id\":\"d04b736a-e874-4137-b191-638e0ff3b4e7\", \"Name\":\"Dragon\", \"Damage\": 70.0, \"Crit\":20}, {\"Id\":\"88221cfe-1f84-41b9-8152-8e36c6a354de\", \"Name\":\"WaterSpell\", \"Damage\": 22.0, \"Crit\":null}, {\"Id\":\"1d3f175b-c067-4359-989d-96562bfa382c\", \"Name\":\"Ork\", \"Damage\": 40.0, \"Crit\":0}, {\"Id\":\"171f6076-4eb5-4a7d-b3f2-2d650cc3d237\", \"Name\":\"RegularSpell\", \"Damage\": 28.0, \"Crit\":null}]"
echo . 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}]" 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, \"Crit\":30}, {\"Id\":\"65ff5f23-1e70-4b79-b3bd-f6eb679dd3b5\", \"Name\":\"Dragon\", \"Damage\": 50.0, \"Crit\":20}, {\"Id\":\"55ef46c4-016c-4168-bc43-6b9b1e86414f\", \"Name\":\"WaterSpell\", \"Damage\": 20.0, \"Crit\":null}, {\"Id\":\"f3fad0f2-a1af-45df-b80d-2e48825773d9\", \"Name\":\"Ork\", \"Damage\": 45.0, \"Crit\":10}, {\"Id\":\"8c20639d-6400-4534-bd0f-ae563f11f57a\", \"Name\":\"WaterSpell\", \"Damage\": 25.0, \"Crit\":null}]"
echo . 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}]" 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, \"Crit\":30}, {\"Id\":\"44c82fbc-ef6d-44ab-8c7a-9fb19a0e7c6e\", \"Name\":\"Dragon\", \"Damage\": 55.0, \"Crit\":10}, {\"Id\":\"2c98cd06-518b-464c-b911-8d787216cddd\", \"Name\":\"WaterSpell\", \"Damage\": 21.0, \"Crit\":null}, {\"Id\":\"951e886a-0fbf-425d-8df5-af2ee4830d85\", \"Name\":\"Ork\", \"Damage\": 55.0, \"Crit\":15}, {\"Id\":\"dcd93250-25a7-4dca-85da-cad2789f7198\", \"Name\":\"FireSpell\", \"Damage\": 23.0, \"Crit\":null}]"
echo . 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}]" 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, \"Crit\":20}, {\"Id\":\"9e8238a4-8a7a-487f-9f7d-a8c97899eb48\", \"Name\":\"Dragon\", \"Damage\": 70.0, \"Crit\":5}, {\"Id\":\"d60e23cf-2238-4d49-844f-c7589ee5342e\", \"Name\":\"WaterSpell\", \"Damage\": 22.0, \"Crit\":null}, {\"Id\":\"fc305a7a-36f7-4d30-ad27-462ca0445649\", \"Name\":\"Ork\", \"Damage\": 40.0, \"Crit\":10}, {\"Id\":\"84d276ee-21ec-4171-a509-c1b88162831c\", \"Name\":\"RegularSpell\", \"Damage\": 28.0, \"Crit\":null}]"
echo . echo .
echo . echo .
@ -95,11 +95,11 @@ read -p "Press any key to resume ..." null
# -------------------------------------------------- # --------------------------------------------------
echo "6) add new packages" 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}]" 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, \"Crit\":50}, {\"Id\":\"aa9999a0-734c-49c6-8f4a-651864b14e62\", \"Name\":\"RegularSpell\", \"Damage\": 50.0, \"Crit\":null}, {\"Id\":\"d6e9c720-9b5a-40c7-a6b2-bc34752e3463\", \"Name\":\"Knight\", \"Damage\": 20.0}, {\"Id\":\"02a9c76e-b17d-427f-9240-2dd49b0d3bfd\", \"Name\":\"RegularSpell\", \"Damage\": 45.0, \"Crit\":null}, {\"Id\":\"2508bf5c-20d7-43b4-8c77-bc677decadef\", \"Name\":\"FireElf\", \"Damage\": 25.0, \"Crit\":70}]"
echo . 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}]" 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, \"Crit\":30}, {\"Id\":\"74635fae-8ad3-4295-9139-320ab89c2844\", \"Name\":\"FireSpell\", \"Damage\": 55.0, \"Crit\":null}, {\"Id\":\"ce6bcaee-47e1-4011-a49e-5a4d7d4245f3\", \"Name\":\"Knight\", \"Damage\": 21.0}, {\"Id\":\"a6fde738-c65a-4b10-b400-6fef0fdb28ba\", \"Name\":\"FireSpell\", \"Damage\": 55.0, \"Crit\":null}, {\"Id\":\"a1618f1e-4f4c-4e09-9647-87e16f1edd2d\", \"Name\":\"FireElf\", \"Damage\": 23.0, \"Crit\":60}]"
echo . 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}]" 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, \"Crit\":30}, {\"Id\":\"3871d45b-b630-4a0d-8bc6-a5fc56b6a043\", \"Name\":\"Dragon\", \"Damage\": 70.0, \"Crit\":20}, {\"Id\":\"166c1fd5-4dcb-41a8-91cb-f45dcd57cef3\", \"Name\":\"Knight\", \"Damage\": 22.0}, {\"Id\":\"237dbaef-49e3-4c23-b64b-abf5c087b276\", \"Name\":\"WaterSpell\", \"Damage\": 40.0, \"Crit\":null}, {\"Id\":\"27051a20-8580-43ff-a473-e986b52f297a\", \"Name\":\"FireElf\", \"Damage\": 28.0, \"Crit\":55}]"
echo . echo .
echo . echo .

View File

@ -41,6 +41,10 @@ There are two parts of the project which are tested through unit tests: the rout
- Starting with the HTTP server made it quite easy testing the application with integration tests (manual using postman or automated using the provided curl script). - Starting with the HTTP server made it quite easy testing the application with integration tests (manual using postman or automated using the provided curl script).
- A separate db helper class would probably make sense for larger, more complex projects, but was overkill here. - A separate db helper class would probably make sense for larger, more complex projects, but was overkill here.
## Unique feature
My unique feature is the ability to crit: Whenever two monsters fight (i.e. no spells involved), they can critically strike for an increase in damage of 50%. Each card has a crit modifier, default to 0.
## Further notes ## Further notes
The curl script was modified to automatically store the authentication tokens in variables. The curl script was modified to automatically store the authentication tokens in variables.

View File

@ -56,6 +56,7 @@ SET default_table_access_method = heap;
CREATE TABLE public.cards ( CREATE TABLE public.cards (
uuid uuid DEFAULT gen_random_uuid() NOT NULL, uuid uuid DEFAULT gen_random_uuid() NOT NULL,
damage double precision DEFAULT 0 NOT NULL, damage double precision DEFAULT 0 NOT NULL,
crit integer DEFAULT 0,
owner uuid, owner uuid,
deck boolean DEFAULT false NOT NULL, deck boolean DEFAULT false NOT NULL,
trade boolean DEFAULT false NOT NULL, trade boolean DEFAULT false NOT NULL,

View File

@ -8,6 +8,7 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Random;
public class Battle { public class Battle {
@ -57,7 +58,8 @@ public class Battle {
this.combatants.left().getAndRemoveCard()), this.combatants.left().getAndRemoveCard()),
new FightDTO( new FightDTO(
this.combatants.right(), this.combatants.right(),
this.combatants.right().getAndRemoveCard())); this.combatants.right().getAndRemoveCard()),
true);
this.log.add(this.createCombatString(round, result)); this.log.add(this.createCombatString(round, result));
@ -130,17 +132,22 @@ public class Battle {
return returnMods; return returnMods;
} }
static RoundResult fight(FightDTO left, FightDTO right) { static RoundResult fight(FightDTO left, FightDTO right, boolean allowCrit) {
if (isImmune(left.card(), right.card())) return new RoundResult(left, right, false, ElementMod.NONE, ElementMod.NONE); if (isImmune(left.card(), right.card())) return new RoundResult(left, right, false, ElementMod.NONE, ElementMod.NONE);
if (isImmune(right.card(), left.card())) return new RoundResult(right, left, false, ElementMod.NONE, ElementMod.NONE); if (isImmune(right.card(), left.card())) return new RoundResult(right, left, false, ElementMod.NONE, ElementMod.NONE);
Pair<ElementMod, ElementMod> dmgMods = getElementMod(left.card(), right.card()); Pair<ElementMod, ElementMod> dmgMods = getElementMod(left.card(), right.card());
boolean leftWins = left.card().damage()*dmgMods.left().percentMod >= right.card().damage()*dmgMods.right().percentMod; allowCrit = allowCrit && left.card().crit() != null && right.card().crit() != null;
double leftCrit = allowCrit && new Random().nextInt() % 100 < left.card().crit() ? 1.5 : 1;
double rightCrit = allowCrit && new Random().nextInt() % 100 < right.card().crit() ? 1.5 : 1;
boolean leftWins = left.card().damage() * dmgMods.left().percentMod * leftCrit >= right.card().damage() * dmgMods.right().percentMod * rightCrit;
return new RoundResult( return new RoundResult(
leftWins ? left : right, leftWins ? left : right,
leftWins ? right : left, leftWins ? right : left,
left.card().damage()*dmgMods.left().percentMod == right.card().damage()*dmgMods.right().percentMod, left.card().damage() * dmgMods.left().percentMod * leftCrit == right.card().damage() * dmgMods.right().percentMod * rightCrit,
leftWins ? dmgMods.left() : dmgMods.right(), leftWins ? dmgMods.left() : dmgMods.right(),
leftWins ? dmgMods.right() : dmgMods.left()); leftWins ? dmgMods.right() : dmgMods.left());
} }

View File

@ -34,6 +34,7 @@ public class Package {
.table(Table.CARDS); .table(Table.CARDS);
if (card.id() != null) query.parameter("uuid", card.id()); if (card.id() != null) query.parameter("uuid", card.id());
if (query.parameter("damage", card.damage()) if (query.parameter("damage", card.damage())
.parameter("crit", card.crit())
.parameter("name", card.name()) .parameter("name", card.name())
.parameter("package", packageUuid) .parameter("package", packageUuid)
.executeUpdate() != 1){ .executeUpdate() != 1){

View File

@ -20,6 +20,7 @@ public class UserCards extends User {
.column("uuid AS id") .column("uuid AS id")
.column("name") .column("name")
.column("damage") .column("damage")
.column("crit")
.condition("owner", userUuid); .condition("owner", userUuid);
if (deckOnly) dbQueryBuilder.condition("deck", true); if (deckOnly) dbQueryBuilder.condition("deck", true);
ArrayList<Card> cards = new ArrayList<>(); ArrayList<Card> cards = new ArrayList<>();

View File

@ -10,5 +10,6 @@ import java.util.UUID;
public record Card( public record Card(
UUID id, UUID id,
String name, String name,
Float damage) { Float damage,
Integer crit) {
} }

View File

@ -93,7 +93,7 @@ public class BattleTest {
Battle.FightDTO fightDTO1 = getFightDTO(card1, dmg1); Battle.FightDTO fightDTO1 = getFightDTO(card1, dmg1);
Battle.FightDTO fightDTO2 = getFightDTO(card2, dmg2); Battle.FightDTO fightDTO2 = getFightDTO(card2, dmg2);
Battle.RoundResult result = Battle.fight(fightDTO1, fightDTO2); Battle.RoundResult result = Battle.fight(fightDTO1, fightDTO2, false);
switch (outcome) { switch (outcome) {
case LEFT_WINS -> { case LEFT_WINS -> {