diff --git a/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/MapleCodeCouponGenerator.java b/src/main/java/tools/mapletools/CodeCouponGenerator.java similarity index 64% rename from tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/MapleCodeCouponGenerator.java rename to src/main/java/tools/mapletools/CodeCouponGenerator.java index 45e2abab35..0539cf4d17 100644 --- a/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/MapleCodeCouponGenerator.java +++ b/src/main/java/tools/mapletools/CodeCouponGenerator.java @@ -1,79 +1,46 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana +package tools.mapletools; - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. +import tools.Pair; - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package maplecodecoupongenerator; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.sql.*; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; /** - * * @author RonanLana - - This application parses the coupon descriptor XML file and automatically generates - code entries on the DB reflecting the descriptions found. Parse time relies on the - sum of coupon codes created and amount of current codes on DB. - - Estimated parse time: 2 minutes (for 100 code entries) + *

+ * This application parses the coupon descriptor XML file and automatically generates + * code entries on the DB reflecting the descriptions found. Parse time relies on the + * sum of coupon codes created and amount of current codes on DB. + *

+ * Estimated parse time: 2 minutes (for 100 code entries) */ -public class MapleCodeCouponGenerator { - static String host = "jdbc:mysql://localhost:3306/cosmic"; - static String driver = "com.mysql.jdbc.Driver"; - static String username = "cosmic_server"; - static String password = "snailshell"; - - static Connection con = null; - static InputStreamReader fileReader = null; - static BufferedReader bufferedReader = null; - - static String fileName = "lib/CouponCodes.img.xml"; - static long currentTime; - - static int initialStringLength = 250; - - static String name; - static boolean active; - static int quantity, duration; - static int maplePoint, nxCredit, nxPrepaid; - - static List> itemList = new ArrayList<>(); - static Pair item; - - - static List activeCoupons = new ArrayList<>(); - static List generatedKeys; - static Set usedCodes = new HashSet<>(); - - static byte status; - +public class CodeCouponGenerator { + private static final File INPUT_FILE = ToolConstants.getInputFile("CouponCodes.img.xml"); + private static final int INITIAL_STRING_LENGTH = 250; + private static final Connection con = SimpleDatabaseConnection.getConnection(); + + private static final List activeCoupons = new ArrayList<>(); + private static final Set usedCodes = new HashSet<>(); + private static final List> itemList = new ArrayList<>(); + + private static BufferedReader bufferedReader = null; + private static long currentTime; + private static String name; + private static boolean active; + private static int quantity; + private static int duration; + private static int maplePoint; + private static int nxCredit; + private static int nxPrepaid; + private static Pair item; + private static List generatedKeys; + private static byte status; + private static void resetCouponPackage() { name = null; active = false; @@ -84,17 +51,17 @@ public class MapleCodeCouponGenerator { nxPrepaid = 0; itemList.clear(); } - + private static String getName(String token) { int i, j; char[] dest; String d; - + i = token.lastIndexOf("name"); i = token.indexOf("\"", i) + 1; //lower bound of the string j = token.indexOf("\"", i); //upper bound - dest = new char[initialStringLength]; + dest = new char[INITIAL_STRING_LENGTH]; try { token.getChars(i, j, dest, 0); } catch (StringIndexOutOfBoundsException e) { @@ -105,14 +72,13 @@ public class MapleCodeCouponGenerator { e.printStackTrace(); try { Thread.sleep(100000000); - } catch (Exception ex) {} + } catch (Exception ex) { + } } - - d = new String(dest); - return(d.trim()); + return new String(dest).trim(); } - + private static String getValue(String token) { int i, j; char[] dest; @@ -122,68 +88,64 @@ public class MapleCodeCouponGenerator { i = token.indexOf("\"", i) + 1; //lower bound of the string j = token.indexOf("\"", i); //upper bound - dest = new char[initialStringLength]; + dest = new char[INITIAL_STRING_LENGTH]; token.getChars(i, j, dest, 0); d = new String(dest); - return(d.trim()); + return (d.trim()); } - + private static void forwardCursor(int st) { String line = null; try { - while(status >= st && (line = bufferedReader.readLine()) != null) { + while (status >= st && (line = bufferedReader.readLine()) != null) { simpleToken(line); } - } - catch(Exception e) { + } catch (Exception e) { e.printStackTrace(); } } - + private static void simpleToken(String token) { - if(token.contains("/imgdir")) { + if (token.contains("/imgdir")) { status -= 1; - } - else if(token.contains("imgdir")) { + } else if (token.contains("imgdir")) { status += 1; } } - + private static void translateToken(String token) { - if(token.contains("/imgdir")) { + if (token.contains("/imgdir")) { status -= 1; - + if (status == 1) { if (active) { activeCoupons.add(new CodeCouponDescriptor(name, quantity, duration, maplePoint, nxCredit, nxPrepaid, itemList)); } - + resetCouponPackage(); } else if (status == 3) { itemList.add(item); } - } - else if(token.contains("imgdir")) { + } else if (token.contains("imgdir")) { status += 1; - + if (status == 4) { item = new Pair<>(-1, -1); } else if (status == 2) { String d = getName(token); - + System.out.println(" Reading coupon '" + d + "'"); name = d; } - } - else { + } else { String d = getName(token); - + if (status == 2) { switch (d) { case "active": - if (Integer.valueOf(getValue(token)) == 0) { + if (Integer.parseInt(getValue(token)) == 0) { forwardCursor(status); resetCouponPackage(); } else { @@ -192,19 +154,19 @@ public class MapleCodeCouponGenerator { break; case "quantity": - quantity = Integer.valueOf(getValue(token)); + quantity = Integer.parseInt(getValue(token)); break; case "duration": - duration = Integer.valueOf(getValue(token)); + duration = Integer.parseInt(getValue(token)); break; case "maplePoint": - maplePoint = Integer.valueOf(getValue(token)); + maplePoint = Integer.parseInt(getValue(token)); break; case "nxCredit": - nxCredit = Integer.valueOf(getValue(token)); + nxCredit = Integer.parseInt(getValue(token)); break; case "nxPrepaid": - nxPrepaid = Integer.valueOf(getValue(token)); + nxPrepaid = Integer.parseInt(getValue(token)); break; } } else if (status == 4) { @@ -219,13 +181,13 @@ public class MapleCodeCouponGenerator { } } } - + private static class CodeCouponDescriptor { protected String name; protected int quantity, duration; protected int nxCredit, maplePoint, nxPrepaid; protected List> itemList; - + protected CodeCouponDescriptor(String name, int quantity, int duration, int maplePoint, int nxCredit, int nxPrepaid, List> itemList) { this.name = name; this.quantity = quantity; @@ -233,109 +195,111 @@ public class MapleCodeCouponGenerator { this.maplePoint = maplePoint; this.nxCredit = nxCredit; this.nxPrepaid = nxPrepaid; - + this.itemList = new ArrayList<>(itemList); } } - + private static String randomizeCouponCode() { return Long.toHexString(Double.doubleToLongBits(Math.random())).substring(0, 15); } - + private static String generateCouponCode() { String newCode; do { newCode = randomizeCouponCode(); } while (usedCodes.contains(newCode)); - + usedCodes.add(newCode); return newCode; } - + private static List getGeneratedKeys(PreparedStatement ps) throws SQLException { if (generatedKeys == null) { generatedKeys = new ArrayList<>(); - + ResultSet rs = ps.getGeneratedKeys(); while (rs.next()) { generatedKeys.add(rs.getInt(1)); } rs.close(); } - + return generatedKeys; } - + private static void commitCodeCouponDescription(CodeCouponDescriptor recipe) throws SQLException { - if (recipe.quantity < 1) return; - + if (recipe.quantity < 1) { + return; + } + System.out.println(" Generating coupon '" + recipe.name + "'"); generatedKeys = null; - + PreparedStatement ps = con.prepareStatement("INSERT IGNORE INTO `nxcode` (`code`, `expiration`) VALUES (?, ?)", Statement.RETURN_GENERATED_KEYS); ps.setLong(2, currentTime + ((long) recipe.duration * 60 * 60 * 1000)); - - for(int i = 0; i < recipe.quantity; i++) { + + for (int i = 0; i < recipe.quantity; i++) { ps.setString(1, generateCouponCode()); ps.addBatch(); } ps.executeBatch(); - + PreparedStatement ps2 = con.prepareStatement("INSERT IGNORE INTO `nxcode_items` (`codeid`, `type`, `item`, `quantity`) VALUES (?, ?, ?, ?)"); if (!recipe.itemList.isEmpty()) { ps2.setInt(2, 5); List keys = getGeneratedKeys(ps); - + for (Pair p : recipe.itemList) { ps2.setInt(3, p.getLeft()); ps2.setInt(4, p.getRight()); - + for (Integer codeid : keys) { ps2.setInt(1, codeid); ps2.addBatch(); } } } - + ps2.setInt(3, 0); if (recipe.nxCredit > 0) { ps2.setInt(2, 0); ps2.setInt(4, recipe.nxCredit); List keys = getGeneratedKeys(ps); - - for(Integer codeid : keys) { + + for (Integer codeid : keys) { ps2.setInt(1, codeid); ps2.addBatch(); } } - + if (recipe.maplePoint > 0) { ps2.setInt(2, 1); ps2.setInt(4, recipe.maplePoint); List keys = getGeneratedKeys(ps); - - for(Integer codeid : keys) { + + for (Integer codeid : keys) { ps2.setInt(1, codeid); ps2.addBatch(); } } - + if (recipe.nxPrepaid > 0) { ps2.setInt(2, 2); ps2.setInt(4, recipe.nxPrepaid); List keys = getGeneratedKeys(ps); - - for(Integer codeid : keys) { + + for (Integer codeid : keys) { ps2.setInt(1, codeid); ps2.addBatch(); } } - + ps2.executeBatch(); ps2.close(); ps.close(); } - + private static void loadUsedCouponCodes() throws SQLException { PreparedStatement ps = con.prepareStatement("SELECT code FROM nxcode", Statement.RETURN_GENERATED_KEYS); ResultSet rs = ps.executeQuery(); @@ -345,51 +309,48 @@ public class MapleCodeCouponGenerator { rs.close(); ps.close(); } - - private static void generateCodeCoupons(String fileName) throws IOException { - fileReader = new InputStreamReader(new FileInputStream(fileName), "UTF-8"); + + private static void generateCodeCoupons(File file) throws IOException { + InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8); bufferedReader = new BufferedReader(fileReader); - + resetCouponPackage(); status = 0; - + System.out.println("Reading XML coupon information..."); String line; - while((line = bufferedReader.readLine()) != null) { + while ((line = bufferedReader.readLine()) != null) { translateToken(line); } bufferedReader.close(); fileReader.close(); System.out.println(); - + try { - Class.forName(driver).newInstance(); - con = DriverManager.getConnection(host, username, password); - System.out.println("Loading DB coupon codes..."); loadUsedCouponCodes(); System.out.println(); - + System.out.println("Saving generated coupons..."); currentTime = System.currentTimeMillis(); for (CodeCouponDescriptor ccd : activeCoupons) { commitCodeCouponDescription(ccd); } System.out.println(); - + con.close(); System.out.println("Done."); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | SQLException e) { + } catch (SQLException e) { e.printStackTrace(); } } - + public static void main(String[] args) { try { - generateCodeCoupons(fileName); - } catch(IOException ex) { - System.out.println("Error reading file '" + fileName + "'"); + generateCodeCoupons(INPUT_FILE); + } catch (IOException ex) { + System.out.println("Error reading file '" + INPUT_FILE.getAbsolutePath() + "'"); } } } diff --git a/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/Pair.java b/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/Pair.java deleted file mode 100644 index b0bcdf2411..0000000000 --- a/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/Pair.java +++ /dev/null @@ -1,121 +0,0 @@ -/* -This file is part of the OdinMS Maple Story Server -Copyright (C) 2008 ~ 2010 Patrick Huy -Matthias Butz -Jan Christian Meyer - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License version 3 -as published by the Free Software Foundation. You may not use, modify -or distribute this program under any other version of the -GNU Affero General Public License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . - */ -package maplecodecoupongenerator; - -/** - * Represents a pair of values. - * - * @author Frz - * @since Revision 333 - * @version 1.0 - * - * @param The type of the left value. - * @param The type of the right value. - */ -public class Pair { - - public E left; - public F right; - - /** - * Class constructor - pairs two objects together. - * - * @param left The left object. - * @param right The right object. - */ - public Pair(E left, F right) { - this.left = left; - this.right = right; - } - - /** - * Gets the left value. - * - * @return The left value. - */ - public E getLeft() { - return left; - } - - /** - * Gets the right value. - * - * @return The right value. - */ - public F getRight() { - return right; - } - - /** - * Turns the pair into a string. - * - * @return Each value of the pair as a string joined with a colon. - */ - @Override - public String toString() { - return left.toString() + ":" + right.toString(); - } - - /** - * Gets the hash code of this pair. - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((left == null) ? 0 : left.hashCode()); - result = prime * result + ((right == null) ? 0 : right.hashCode()); - return result; - } - - /** - * Checks to see if two pairs are equal. - */ - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Pair other = (Pair) obj; - if (left == null) { - if (other.left != null) { - return false; - } - } else if (!left.equals(other.left)) { - return false; - } - if (right == null) { - if (other.right != null) { - return false; - } - } else if (!right.equals(other.right)) { - return false; - } - return true; - } -} \ No newline at end of file diff --git a/tools/input/.gitignore b/tools/input/.gitignore index 9e88c6e0f0..ff456c3654 100644 --- a/tools/input/.gitignore +++ b/tools/input/.gitignore @@ -1,4 +1,5 @@ * !*/ !/cosmetics/** -!.gitignore \ No newline at end of file +!.gitignore +!CouponCodes.img.xml \ No newline at end of file diff --git a/tools/MapleCodeCouponGenerator/lib/CouponCodes.img.xml b/tools/input/CouponCodes.img.xml similarity index 53% rename from tools/MapleCodeCouponGenerator/lib/CouponCodes.img.xml rename to tools/input/CouponCodes.img.xml index 9fccae135f..8ce30f6212 100644 --- a/tools/MapleCodeCouponGenerator/lib/CouponCodes.img.xml +++ b/tools/input/CouponCodes.img.xml @@ -4,17 +4,17 @@ - - - + + + - - + + - - + + @@ -22,17 +22,17 @@ - - - + + + - - + + - - + +