From 682bf8d77d8b785f8a7c50ae96c9b6a276b7b885 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 14 Dec 2018 14:48:43 -0500 Subject: [PATCH] http api: add loot tracker service and client Co-authored-by: TheStonedTurtle <29030969+TheStonedTurtle@users.noreply.github.com> --- .../http/api/loottracker/GameItem.java | 34 ++++ .../http/api/loottracker/LootRecord.java | 40 ++++ .../http/api/loottracker/LootRecordType.java | 33 ++++ .../api/loottracker/LootTrackerClient.java | 77 ++++++++ .../http/service/loottracker/LootResult.java | 40 ++++ .../loottracker/LootTrackerController.java | 79 ++++++++ .../loottracker/LootTrackerService.java | 173 ++++++++++++++++++ 7 files changed, 476 insertions(+) create mode 100644 http-api/src/main/java/net/runelite/http/api/loottracker/GameItem.java create mode 100644 http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java create mode 100644 http-api/src/main/java/net/runelite/http/api/loottracker/LootRecordType.java create mode 100644 http-api/src/main/java/net/runelite/http/api/loottracker/LootTrackerClient.java create mode 100644 http-service/src/main/java/net/runelite/http/service/loottracker/LootResult.java create mode 100644 http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java create mode 100644 http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java diff --git a/http-api/src/main/java/net/runelite/http/api/loottracker/GameItem.java b/http-api/src/main/java/net/runelite/http/api/loottracker/GameItem.java new file mode 100644 index 0000000000..886dac42b6 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/loottracker/GameItem.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, TheStonedTurtle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.api.loottracker; + +import lombok.Value; + +@Value +public class GameItem +{ + private int id; + private int qty; +} diff --git a/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java b/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java new file mode 100644 index 0000000000..fb43a1605a --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecord.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, TheStonedTurtle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.api.loottracker; + +import java.util.Collection; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class LootRecord +{ + private String eventId; + private LootRecordType type; + private Collection drops; +} diff --git a/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecordType.java b/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecordType.java new file mode 100644 index 0000000000..c91817b410 --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/loottracker/LootRecordType.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, TheStonedTurtle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.api.loottracker; + +public enum LootRecordType +{ + NPC, + PLAYER, + EVENT, + UNKNOWN +} diff --git a/http-api/src/main/java/net/runelite/http/api/loottracker/LootTrackerClient.java b/http-api/src/main/java/net/runelite/http/api/loottracker/LootTrackerClient.java new file mode 100644 index 0000000000..06c42ab24d --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/loottracker/LootTrackerClient.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.api.loottracker; + +import com.google.gson.Gson; +import java.io.IOException; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.runelite.http.api.RuneLiteAPI; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.HttpUrl; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +@Slf4j +@AllArgsConstructor +public class LootTrackerClient +{ + private static final MediaType JSON = MediaType.parse("application/json"); + private static final Gson GSON = RuneLiteAPI.GSON; + + private final UUID uuid; + + public void submit(LootRecord lootRecord) + { + HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() + .addPathSegment("loottracker") + .build(); + + Request request = new Request.Builder() + .header(RuneLiteAPI.RUNELITE_AUTH, uuid.toString()) + .post(RequestBody.create(JSON, GSON.toJson(lootRecord))) + .url(url) + .build(); + + RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback() + { + @Override + public void onFailure(Call call, IOException e) + { + log.warn("unable to submit loot", e); + } + + @Override + public void onResponse(Call call, Response response) throws IOException + { + log.debug("Submitted loot"); + } + }); + } +} diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootResult.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootResult.java new file mode 100644 index 0000000000..5bfd7afee0 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/loottracker/LootResult.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.loottracker; + +import java.time.Instant; +import lombok.Data; +import net.runelite.http.api.loottracker.LootRecordType; + +@Data +class LootResult +{ + private int killId; + private Instant time; + private LootRecordType type; + private String eventId; + private int itemId; + private int itemQuantity; +} diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java new file mode 100644 index 0000000000..baa01065e3 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerController.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, TheStonedTurtle + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.loottracker; + +import com.google.api.client.http.HttpStatusCodes; +import java.io.IOException; +import java.util.Collection; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import net.runelite.http.api.loottracker.LootRecord; +import net.runelite.http.service.account.AuthFilter; +import net.runelite.http.service.account.beans.SessionEntry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/loottracker") +public class LootTrackerController +{ + @Autowired + private LootTrackerService service; + + @Autowired + private AuthFilter auth; + + @RequestMapping(method = RequestMethod.POST) + public void storeLootRecord(HttpServletRequest request, HttpServletResponse response, @RequestBody LootRecord record) throws IOException + { + SessionEntry e = auth.handle(request, response); + if (e == null) + { + response.setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED); + return; + } + + service.store(record, e.getUser()); + response.setStatus(HttpStatusCodes.STATUS_CODE_OK); + } + + @RequestMapping + public Collection getLootRecords(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "count", defaultValue = "1024") int count) throws IOException + { + SessionEntry e = auth.handle(request, response); + if (e == null) + { + response.setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED); + return null; + } + + return service.get(e.getUser(), count); + } +} \ No newline at end of file diff --git a/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java new file mode 100644 index 0000000000..3c94eb3687 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/loottracker/LootTrackerService.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2018, TheStonedTurtle + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.loottracker; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import net.runelite.http.api.loottracker.GameItem; +import net.runelite.http.api.loottracker.LootRecord; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.sql2o.Connection; +import org.sql2o.Query; +import org.sql2o.Sql2o; + +@Service +public class LootTrackerService +{ + // Table for storing individual LootRecords + private static final String CREATE_KILLS = "CREATE TABLE IF NOT EXISTS `kills` (\n" + + " `id` INT AUTO_INCREMENT UNIQUE,\n" + + " `time` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),\n" + + " `accountId` INT NOT NULL,\n" + + " `type` enum('NPC', 'PLAYER', 'EVENT', 'UNKNOWN') NOT NULL,\n" + + " `eventId` VARCHAR(255) NOT NULL,\n" + + " PRIMARY KEY (id),\n" + + " FOREIGN KEY (accountId) REFERENCES sessions(user) ON DELETE CASCADE,\n" + + " INDEX idx_acc (accountId, time)," + + " INDEX idx_time (time)" + + ") ENGINE=InnoDB"; + + // Table for storing Items received as loot for individual LootRecords + private static final String CREATE_DROPS = "CREATE TABLE IF NOT EXISTS `drops` (\n" + + " `killId` INT NOT NULL,\n" + + " `itemId` INT NOT NULL,\n" + + " `itemQuantity` INT NOT NULL,\n" + + " FOREIGN KEY (killId) REFERENCES kills(id) ON DELETE CASCADE\n" + + ") ENGINE=InnoDB"; + + // Queries for inserting kills + private static final String INSERT_KILL_QUERY = "INSERT INTO kills (accountId, type, eventId) VALUES (:accountId, :type, :eventId)"; + private static final String INSERT_DROP_QUERY = "INSERT INTO drops (killId, itemId, itemQuantity) VALUES (LAST_INSERT_ID(), :itemId, :itemQuantity)"; + + private static final String SELECT_LOOT_QUERY = "SELECT killId,time,type,eventId,itemId,itemQuantity FROM kills JOIN drops ON drops.killId = kills.id WHERE accountId = :accountId ORDER BY TIME DESC LIMIT :limit"; + + private final Sql2o sql2o; + + @Autowired + public LootTrackerService(@Qualifier("Runelite SQL2O") Sql2o sql2o) + { + this.sql2o = sql2o; + + // Ensure necessary tables exist + try (Connection con = sql2o.open()) + { + con.createQuery(CREATE_KILLS).executeUpdate(); + con.createQuery(CREATE_DROPS).executeUpdate(); + } + } + + /** + * Store LootRecord + * + * @param record LootRecord to store + * @param accountId runelite account id to tie data too + */ + public void store(LootRecord record, int accountId) + { + try (Connection con = sql2o.beginTransaction()) + { + // Kill Entry Query + con.createQuery(INSERT_KILL_QUERY, true) + .addParameter("accountId", accountId) + .addParameter("type", record.getType()) + .addParameter("eventId", record.getEventId()) + .executeUpdate(); + + Query insertDrop = con.createQuery(INSERT_DROP_QUERY); + + // Append all queries for inserting drops + for (GameItem drop : record.getDrops()) + { + insertDrop + .addParameter("itemId", drop.getId()) + .addParameter("itemQuantity", drop.getQty()) + .addToBatch(); + } + + insertDrop.executeBatch(); + con.commit(false); + } + } + + public Collection get(int accountId, int limit) + { + List lootResults; + + try (Connection con = sql2o.open()) + { + lootResults = con.createQuery(SELECT_LOOT_QUERY) + .addParameter("accountId", accountId) + .addParameter("limit", limit) + .executeAndFetch(LootResult.class); + } + + int killId = -1; + List lootRecords = new ArrayList<>(); + List gameItems = new ArrayList<>(); + + for (LootResult lootResult : lootResults) + { + if (killId != lootResult.getKillId()) + { + killId = lootResult.getKillId(); + + if (!gameItems.isEmpty()) + { + LootRecord lootRecord = new LootRecord(lootResult.getEventId(), lootResult.getType(), gameItems); + lootRecords.add(lootRecord); + } + + gameItems = new ArrayList<>(); + } + + GameItem gameItem = new GameItem(lootResult.getItemId(), lootResult.getItemQuantity()); + gameItems.add(gameItem); + } + + if (!gameItems.isEmpty()) + { + LootResult lootResult = lootResults.get(lootResults.size() - 1); + LootRecord lootRecord = new LootRecord(lootResult.getEventId(), lootResult.getType(), gameItems); + lootRecords.add(lootRecord); + } + + return lootRecords; + } + + @Scheduled(fixedDelay = 15 * 60 * 1000) + public void expire() + { + try (Connection con = sql2o.open()) + { + con.createQuery("delete from kills where time + interval 30 day < current_timestamp()") + .executeUpdate(); + } + } +}