From 17a2914a0ea2b7eeac31a3b4801f6357f675576a Mon Sep 17 00:00:00 2001 From: test Date: Tue, 6 Aug 2024 03:41:58 +1000 Subject: [PATCH] Add deposit sheet date --- .../manager/v2/impl/pw/CommandManager2.java | 1 + .../v2/impl/pw/commands/BankCommands.java | 8 +- .../v2/impl/pw/commands/WarCommands.java | 116 ++++++++++++++++-- .../java/link/locutus/discord/db/BankDB.java | 34 +++-- 4 files changed, 141 insertions(+), 18 deletions(-) diff --git a/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/CommandManager2.java b/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/CommandManager2.java index 3b435389..4b443c9e 100644 --- a/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/CommandManager2.java +++ b/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/CommandManager2.java @@ -242,6 +242,7 @@ public CommandManager2 registerDefaults() { getCommands().registerMethod(new WarCommands(), List.of("sheets_ia"), "ActivitySheetDate", "activity_date"); getCommands().registerMethod(new WarCommands(), List.of("sheets_ia"), "WarDecSheetDate", "declares_date"); + getCommands().registerMethod(new WarCommands(), List.of("sheets_ia"), "DepositSheetDate", "deposits_date"); getCommands().registerMethod(new AdminCommands(), List.of("admin", "settings"), "unsetNews", "subscribe"); getCommands().registerMethod(new AdminCommands(), List.of("admin", "settings"), "unsetKeys", "unset"); diff --git a/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/BankCommands.java b/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/BankCommands.java index a43f1450..b2313b9e 100644 --- a/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/BankCommands.java +++ b/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/BankCommands.java @@ -2655,11 +2655,15 @@ public void largest(Map total, Map l @Command(desc = "Get a sheet of in-game transfers for nations") @RolePermission(value = Roles.ECON) - public String getIngameNationTransfers(@Me IMessageIO channel, @Me GuildDB db, @AllowDeleted Set senders, @AllowDeleted Set receivers, @Arg("Only transfers after timeframe") @Default("%epoch%") @Timestamp long timeframe, @Switch("s") SpreadSheet sheet) throws IOException, GeneralSecurityException { + public String getIngameNationTransfers(@Me IMessageIO channel, @Me GuildDB db, @AllowDeleted Set senders, @AllowDeleted Set receivers, + @Arg("Only transfers after timeframe") @Default("%epoch%") @Timestamp long start_time, + @Switch("e") @Timestamp Long end_time, + @Switch("s") SpreadSheet sheet) throws IOException, GeneralSecurityException { + if (end_time == null) end_time = Long.MAX_VALUE; if (sheet == null) sheet = SpreadSheet.create(db, SheetKey.BANK_TRANSACTION_SHEET); Set senderIds = senders.stream().map(NationOrAllianceOrGuild::getIdLong).collect(Collectors.toSet()); Set receiverIds = receivers.stream().map(NationOrAllianceOrGuild::getIdLong).collect(Collectors.toSet()); - List transactions = Locutus.imp().getBankDB().getTransactionsByBySenderOrReceiver(senderIds, receiverIds, timeframe); + List transactions = Locutus.imp().getBankDB().getTransactionsByBySenderOrReceiver(senderIds, receiverIds, start_time, end_time); transactions.removeIf(transaction2 -> { NationOrAllianceOrGuild sender = transaction2.getSenderObj(); NationOrAllianceOrGuild receiver = transaction2.getReceiverObj(); diff --git a/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/WarCommands.java b/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/WarCommands.java index c87b2da7..a959813d 100644 --- a/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/WarCommands.java +++ b/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/WarCommands.java @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import link.locutus.discord.Locutus; @@ -41,12 +42,7 @@ import link.locutus.discord.db.guild.GuildKey; import link.locutus.discord.db.guild.SheetKey; import link.locutus.discord.gpt.GPTUtil; -import link.locutus.discord.pnw.AllianceList; -import link.locutus.discord.pnw.BeigeReason; -import link.locutus.discord.pnw.NationList; -import link.locutus.discord.pnw.NationScoreMap; -import link.locutus.discord.pnw.SimpleNationList; -import link.locutus.discord.pnw.Spyop; +import link.locutus.discord.pnw.*; import link.locutus.discord.user.Roles; import link.locutus.discord.util.MarkupUtil; import link.locutus.discord.util.MathMan; @@ -2471,6 +2467,111 @@ private static void generateSpySheet(SpreadSheet sheet, Map nations, + boolean deposit, + boolean withdraw, + @Arg("Date to start from") + @Timestamp long start_time, + @Timestamp long end_time, + @Switch("d") boolean split_deposit_withdraw, + @Switch("t") boolean by_turn, + @Switch("s") SpreadSheet sheet) throws GeneralSecurityException, IOException { + if (split_deposit_withdraw && (!deposit || !withdraw)) { + throw new IllegalArgumentException("Splitting off and def requires both `off` and `def` to be true"); + } + if (!deposit && !withdraw) { + throw new IllegalArgumentException("At least one of `off` or `def` must be true"); + } + long startTurn = TimeUtil.getTurn(start_time); + long endTurn = TimeUtil.getTurn(end_time); + + long endDay = TimeUtil.getDay(TimeUtil.getTimeFromTurn(TimeUtil.getTurn(end_time) + 11)); + long startDay = TimeUtil.getDay(start_time); + + long numDays = endDay - startDay + 1; + if (numDays > 365) { + throw new IllegalArgumentException("Too many days: `" + numDays + " (max 365)"); + } + if (endTurn <= startTurn) { + throw new IllegalArgumentException("End time must be after start time (2h)"); + } + if (by_turn && endTurn - startTurn > 365) { + throw new IllegalArgumentException("Too many turns: `" + (endTurn - startTurn + 1) + " (max 365)"); + } + + Set nationIds = new LongOpenHashSet(nations.stream().map(NationOrAllianceOrGuild::getIdLong).collect(Collectors.toSet())); + List records = Locutus.imp().getBankDB().getTransactionsByBySenderOrReceiver(nationIds, nationIds, start_time, end_time); + Predicate allowNation = f -> nationIds.contains((long) f); + + NationDB natDb = Locutus.imp().getNationDB(); + Map> deposited = new Int2ObjectOpenHashMap<>(); + Map> withdrawn = new Int2ObjectOpenHashMap<>(); + Function toTime = by_turn ? f -> TimeUtil.getTurn(f.getDate()) : f -> TimeUtil.getDay(f.getDate()); + for (Transaction2 tx : records) { + long time = toTime.apply(tx); + if (tx.isSenderNation() && allowNation.test((int) tx.sender_id)) { + deposited.computeIfAbsent((int) tx.sender_id, f -> new Long2DoubleOpenHashMap()).merge(time, tx.convertedTotal(), Double::sum); + } else if (tx.isReceiverNation() && allowNation.test((int) tx.receiver_id)) { + withdrawn.computeIfAbsent((int) tx.receiver_id, f -> new Long2DoubleOpenHashMap()).merge(time, tx.convertedTotal(), Double::sum); + } + } + + if (sheet == null) { + sheet = SpreadSheet.create(db, by_turn ? SheetKey.ACTIVITY_SHEET_TURN : SheetKey.ACTIVITY_SHEET_DAY); + } + + long startUnit = by_turn ? startTurn : startDay; + long endUnit = by_turn ? endTurn : endDay; + + List header = new ArrayList<>(Arrays.asList("nation", "alliance", "cities")); + for (long timeUnit = startUnit; timeUnit <= endUnit; timeUnit++) { + long time = by_turn ? TimeUtil.getTimeFromTurn(timeUnit) : TimeUtil.getTimeFromDay(timeUnit); + SimpleDateFormat format = by_turn ? TimeUtil.DD_MM_YYYY_HH : TimeUtil.DD_MM_YYYY; + header.add(format.format(new Date(time))); + } + + sheet.setHeader(header); + for (DBNation nation : nations) { + Map depActivity = deposited.getOrDefault(nation.getNation_id(), new Long2DoubleOpenHashMap()); + Map withActivity = withdrawn.getOrDefault(nation.getNation_id(), new Long2DoubleOpenHashMap()); + Function formatFunc; + if (split_deposit_withdraw) { + formatFunc = f -> { + double depAmt = depActivity.getOrDefault(f, 0d); + double withAmt = withActivity.getOrDefault(f, 0d); + if (depAmt == 0 && withAmt == 0) return ""; + return MathMan.format(depAmt) + "/" + MathMan.format(withAmt); + }; + } else { + formatFunc = f -> { + double amt = (depActivity.getOrDefault(f, 0d) - withActivity.getOrDefault(f, 0d)); + return amt == 0 ? "" : MathMan.format(amt); + }; + } + header.set(0, MarkupUtil.sheetUrl(nation.getNation(), nation.getUrl())); + header.set(1, MarkupUtil.sheetUrl(nation.getAllianceName(), nation.getAllianceUrl())); + header.set(2, nation.getCities() + ""); + int index = 3; + for (long timeUnit = startUnit; timeUnit <= endUnit; timeUnit++) { + header.set(index, formatFunc.apply(timeUnit)); + index++; + } + sheet.addRow(header); + } + + sheet.updateClearCurrentTab(); + sheet.updateWrite(); + + sheet.attach(io.create(), "activity").send(); + return null; + } + @RolePermission(value = {Roles.MILCOM, Roles.INTERNAL_AFFAIRS,Roles.ECON}, any=true) @Command(desc = "Generate a sheet of nation login activity from a nation id over a timeframe\n" + "The columns are the 7 days of the week and then turns of the day (12)\n" + @@ -2488,7 +2589,8 @@ public String ActivitySheetFromId(@Me IMessageIO io, @Me GuildDB db, int nationI } @RolePermission(value = {Roles.MILCOM, Roles.INTERNAL_AFFAIRS,Roles.ECON}, any=true) - @Command(desc = "Generate a sheet of nation war declare activity from a nation id over a timeframe") + @Command(desc = "Generate a sheet of per nation war declare activity over a timeframe\n" + + "The columns represent the time unit (either turns or days) when wars are declared for each nation") public String WarDecSheetDate(@Me IMessageIO io, @Me GuildDB db, Set nations, boolean off, boolean def, diff --git a/src/main/java/link/locutus/discord/db/BankDB.java b/src/main/java/link/locutus/discord/db/BankDB.java index 8fc570cd..a898e204 100644 --- a/src/main/java/link/locutus/discord/db/BankDB.java +++ b/src/main/java/link/locutus/discord/db/BankDB.java @@ -1,6 +1,7 @@ package link.locutus.discord.db; import com.politicsandwar.graphql.model.*; +import com.politicsandwar.graphql.model.SortOrder; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -30,14 +31,8 @@ import org.example.jooq.bank.tables.records.Transactions_2Record; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jooq.Condition; -import org.jooq.GroupField; -import org.jooq.Index; -import org.jooq.InsertSetMoreStep; -import org.jooq.Query; +import org.jooq.*; import org.jooq.Record; -import org.jooq.Result; -import org.jooq.SortField; import org.jooq.exception.InvalidResultException; import org.jooq.impl.DSL; @@ -723,8 +718,29 @@ public List getTransactionsbyId(Collection ids) { return getTransactions(TRANSACTIONS_2.TX_ID.in(idsSorted), TRANSACTIONS_2.TX_ID.desc(), null); } - public List getTransactionsByBySenderOrReceiver(Set senders, Set receivers, long minDateMs) { - return getTransactions(TRANSACTIONS_2.TX_DATETIME.ge(minDateMs).and(TRANSACTIONS_2.SENDER_ID.in(senders).and(TRANSACTIONS_2.RECEIVER_ID.in(receivers))), TRANSACTIONS_2.TX_ID.desc(), null); + public List getTransactionsByBySenderOrReceiver(Set senders, Set receivers, long minDateMs, long maxDateMs) { + List addConditions = new ArrayList<>(); + if (minDateMs > 0) { + addConditions.add(TRANSACTIONS_2.TX_DATETIME.ge(minDateMs)); + } + if (maxDateMs != Long.MAX_VALUE) { + addConditions.add(TRANSACTIONS_2.TX_DATETIME.le(maxDateMs)); + } + if (senders.size() > 0) { + if (senders.size() == 1) { + addConditions.add(TRANSACTIONS_2.SENDER_ID.eq(senders.iterator().next())); + } else { + addConditions.add(TRANSACTIONS_2.SENDER_ID.in(senders)); + } + } + if (receivers.size() > 0) { + if (receivers.size() == 1) { + addConditions.add(TRANSACTIONS_2.RECEIVER_ID.eq(receivers.iterator().next())); + } else { + addConditions.add(TRANSACTIONS_2.RECEIVER_ID.in(receivers)); + } + } + return getTransactions(DSL.and(addConditions), TRANSACTIONS_2.TX_ID.desc(), null); } public List getTransactionsByBySender(Set senders, long minDateMs) {