From 050b016143425b0eb8c897e5329ee22ae533b4b6 Mon Sep 17 00:00:00 2001 From: Vylion Date: Thu, 21 Apr 2016 22:34:36 +0200 Subject: [PATCH] Pole system finished. --- .idea/misc.xml | 2 +- src/elements/Chat.java | 123 ++++++++++++++++++ src/elements/Persistence.java | 76 +++++++++++ .../exceptions/PoleBlockedException.java | 11 ++ .../exceptions/ReadErrorException.java | 26 ++++ .../exceptions/SaveErrorException.java | 26 ++++ .../exceptions/UserNotExistingException.java | 11 ++ src/main/Main.java | 4 + src/main/Vylbot.java | 122 ++++++++++------- 9 files changed, 350 insertions(+), 51 deletions(-) create mode 100644 src/elements/Chat.java create mode 100644 src/elements/Persistence.java create mode 100644 src/elements/exceptions/PoleBlockedException.java create mode 100644 src/elements/exceptions/ReadErrorException.java create mode 100644 src/elements/exceptions/SaveErrorException.java create mode 100644 src/elements/exceptions/UserNotExistingException.java diff --git a/.idea/misc.xml b/.idea/misc.xml index 9afc2ea..1577011 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -58,7 +58,7 @@ - + \ No newline at end of file diff --git a/src/elements/Chat.java b/src/elements/Chat.java new file mode 100644 index 0000000..2cc2636 --- /dev/null +++ b/src/elements/Chat.java @@ -0,0 +1,123 @@ +package elements; + +import elements.exceptions.UserNotExistingException; + +import java.time.LocalDate; +import java.util.*; + +/** + * Created by vylion on 4/21/16. + */ +public class Chat { + private static final String DATE_TAG = "Date="; + + private Map users; + private LocalDate lastPole; + + public Chat() { + users = new HashMap(); + lastPole = null; + } + + public boolean exists(String user) { + return users.containsKey(user); + } + + public void add(String user) { + users.put(user, 0); + } + + public void add(String user, int p) { + users.put(user, p); + } + + public void winPole(String user) { + if(!users.containsKey(user)) add(user); + users.replace(user, users.get(user)+1); + lastPole = LocalDate.now(); + } + + public boolean availablePole() { + LocalDate today = LocalDate.now(); + + return (lastPole == null || today.isAfter(lastPole)); + } + + public String getRanking() { + List> top; + String ranking = ""; + Map.Entry[] ts = new Map.Entry[users.size()]; + + top = Arrays.asList((users.entrySet().toArray(ts))); + top.sort(new UserComparator()); + + for(int i = 0; i < top.size(); i++) { + ranking += "[" + (i+1) + ".] @" + getUsername(top.get(i)) + ": "; + ranking += getPoles(top.get(i)) + "\n"; + } + + return ranking; + } + + public String toTxt() { + String s = DATE_TAG; + if(lastPole == null) s += "null\n"; + else s += lastPole + "\n"; + Iterator it = users.entrySet().iterator(); + + while(it.hasNext()) { + Map.Entry entry = (Map.Entry) it.next(); + s += getUsername(entry) + ":" + getPoles(entry) + "\n"; + } + + return s; + } + + public static Chat fromTxt(List lines) { + Chat c = new Chat(); + + if(lines.get(0).startsWith(DATE_TAG)) { + String pole = lines.get(0).substring(DATE_TAG.length()); + String[] reading = pole.split("-"); + LocalDate poleDate = LocalDate.of(Integer.parseInt(reading[0]), + Integer.parseInt(reading[1]), Integer.parseInt(reading[2])); + c.setPole(poleDate); + + for(int i = 1; i < lines.size(); i++) { + reading = lines.get(i).split(":"); + c.add(reading[0],Integer.parseInt(reading[1])); + } + } + + else { + for(int i = 0; i < lines.size(); i++) { + String[] reading = lines.get(i).split(":"); + c.add(reading[0],Integer.parseInt(reading[1])); + } + } + + + return c; + } + + private void setPole(LocalDate d) { + lastPole = d; + } + + private String getUsername(Map.Entry e) { + return e.getKey(); + } + + private int getPoles(Map.Entry e) { + return e.getValue(); + } +} + +class UserComparator implements Comparator { + + @Override + public int compare(Map.Entry entr1, Map.Entry entr2) { + + return ((Integer) entr2.getValue()).compareTo((Integer) entr1.getValue()); + } +} diff --git a/src/elements/Persistence.java b/src/elements/Persistence.java new file mode 100644 index 0000000..b6b318f --- /dev/null +++ b/src/elements/Persistence.java @@ -0,0 +1,76 @@ +package elements; + +import elements.exceptions.ReadErrorException; +import elements.exceptions.SaveErrorException; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Created by vylion on 4/14/16. + */ +public class Persistence { + private static Persistence persistence; + + private Persistence() { + + } + + public static Persistence getInstance() { + if(persistence == null) persistence = new Persistence(); + return persistence; + } + + public void saveChat(long chat_id, Chat c) throws SaveErrorException { + try { + List lines = Arrays.asList(c.toTxt().split("\n")); + + Path file = Paths.get("chats/" + chat_id + ".txt"); + if (!Files.exists(file.getParent())) + Files.createDirectories(file.getParent()); + Files.write(file, lines, Charset.forName("UTF-8")); + } catch (IOException e) { + throw new SaveErrorException(chat_id); + } + + return; + } + + public HashMap readChats() throws ReadErrorException { + HashMap chats = new HashMap(); + + if(!Files.exists(Paths.get("chats/"))) return chats; + + try { + String filename; + Chat chat; + List files = Files.walk(Paths.get("chats/"), 1).collect(Collectors.toList()); + Path file; + List lines; + + for(int i = 0; i < files.size(); i++) { + file = files.get(i); + filename = file.getFileName().toString(); + if(filename.endsWith(".txt")) { + filename = filename.substring(0,filename.length() - 4); + System.out.println("Reading " + filename); + + lines = Files.readAllLines(file); + chats.put(Long.parseLong(filename), Chat.fromTxt(lines)); + } + } + } catch (IOException e) { + e.printStackTrace(); + throw new ReadErrorException(); + } + + return chats; + } +} diff --git a/src/elements/exceptions/PoleBlockedException.java b/src/elements/exceptions/PoleBlockedException.java new file mode 100644 index 0000000..db889ec --- /dev/null +++ b/src/elements/exceptions/PoleBlockedException.java @@ -0,0 +1,11 @@ +package elements.exceptions; + +/** + * Created by vylion on 4/21/16. + */ +public class PoleBlockedException extends Exception { + + public PoleBlockedException() { + super("La pole de hoy ya ha sido conseguida. Vuélvelo a intentar mañana."); + } +} diff --git a/src/elements/exceptions/ReadErrorException.java b/src/elements/exceptions/ReadErrorException.java new file mode 100644 index 0000000..7142929 --- /dev/null +++ b/src/elements/exceptions/ReadErrorException.java @@ -0,0 +1,26 @@ +package elements.exceptions; + +import java.io.IOException; + +/** + * Created by vylion on 4/15/16. + */ +public class ReadErrorException extends IOException { + public ReadErrorException() { + super("Ha ocurrido un error al leer los datos. " + + "Contacta con mi creador o algo. io k se xdxd"); + } + public ReadErrorException(long chat_id) { + super("Ha ocurrido un error al leer los datos del chat " + chat_id + + ". Contacta con mi creador o algo. io k se xdxd"); + } + + @Override + public String getLocalizedMessage() { + return "Couldn't read file. You're on your own on this one."; + } + + public String getLocalizedMessage(long chat_id) { + return "Couldn't read file " + chat_id + ". You're on your own on this one."; + } +} diff --git a/src/elements/exceptions/SaveErrorException.java b/src/elements/exceptions/SaveErrorException.java new file mode 100644 index 0000000..c2a3ee7 --- /dev/null +++ b/src/elements/exceptions/SaveErrorException.java @@ -0,0 +1,26 @@ +package elements.exceptions; + +import java.io.IOException; + +/** + * Created by vylion on 4/15/16. + */ +public class SaveErrorException extends IOException { + public SaveErrorException() { + super("Ha ocurrido un error al guardar los datos. Contacta con mi creador o algo. io k se xdxd"); + } + + public SaveErrorException(long chat_id) { + super("Ha ocurrido un error al guardar los datos del chat " + chat_id + + ". Contacta con mi creador o algo. io k se xdxd"); + } + + @Override + public String getLocalizedMessage() { + return "Couldn't save to file. You're on your own on this one."; + } + + public String getLocalizedMessage(long chat_id) { + return "Couldn't save " + chat_id + " to file. You're on your own on this one."; + } +} diff --git a/src/elements/exceptions/UserNotExistingException.java b/src/elements/exceptions/UserNotExistingException.java new file mode 100644 index 0000000..8e9d05e --- /dev/null +++ b/src/elements/exceptions/UserNotExistingException.java @@ -0,0 +1,11 @@ +package elements.exceptions; + +/** + * Created by vylion on 4/21/16. + */ +public class UserNotExistingException extends Exception { + + public UserNotExistingException() { + super("No tengo constancia de ninguna persona con ese nombre de usuario."); + } +} diff --git a/src/main/Main.java b/src/main/Main.java index 1b20fda..0714418 100644 --- a/src/main/Main.java +++ b/src/main/Main.java @@ -1,6 +1,7 @@ package main; import com.mashape.unirest.http.exceptions.UnirestException; +import elements.exceptions.ReadErrorException; /** * Created by vylion on 4/1/16. @@ -16,6 +17,9 @@ public class Main { } catch (UnirestException e) { System.out.println("Unirest Error catched."); e.printStackTrace(); + } catch (ReadErrorException e) { + System.out.println(e.getMessage()); + e.printStackTrace(); } } } diff --git a/src/main/Vylbot.java b/src/main/Vylbot.java index a61b8cf..685ab39 100644 --- a/src/main/Vylbot.java +++ b/src/main/Vylbot.java @@ -4,6 +4,11 @@ import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.JsonNode; import com.mashape.unirest.http.Unirest; import com.mashape.unirest.http.exceptions.UnirestException; +import elements.Chat; +import elements.Persistence; +import elements.exceptions.PoleBlockedException; +import elements.exceptions.ReadErrorException; +import elements.exceptions.SaveErrorException; import org.json.JSONArray; import org.json.JSONObject; @@ -23,8 +28,9 @@ public class Vylbot { private static final int COMMAND_COUNT_START = 0; private static final int COMMAND_START = COMMAND_COUNT_START; private static final int COMMAND_HELP = COMMAND_START + 1; - private static final int COMMAND_POLE = COMMAND_HELP + 1; - private static final int COMMAND_COUNT_END = COMMAND_POLE + 1; + private static final int COMMAND_RANKING = COMMAND_HELP + 1; + private static final int COMMAND_TALIBOT_STATS = COMMAND_RANKING + 1; + private static final int COMMAND_COUNT_END = COMMAND_TALIBOT_STATS + 1; private static final int WARNING_COUNT_START = COMMAND_COUNT_END; private static final int WARNING_UNKNOWN_ERROR = WARNING_COUNT_START; @@ -34,13 +40,17 @@ public class Vylbot { private static final int WARNING_NO_GROUP = WARNING_NOT_IMPLEMENTED + 1; private static final int WARNING_COUNT_END = WARNING_NO_GROUP + 1; - private ArrayList commands; + private List commands; + private Map chats; - public Vylbot() { + public Vylbot() throws ReadErrorException { + chats = Persistence.getInstance().readChats(); + commands = new ArrayList<>(); commands.add(COMMAND_START, "/start"); commands.add(COMMAND_HELP, "/help"); - commands.add(COMMAND_POLE, "/pole"); + commands.add(COMMAND_RANKING, "/ranking"); + commands.add(COMMAND_TALIBOT_STATS, "!pole stats"); } public String getUsername() { @@ -181,10 +191,9 @@ public class Vylbot { if (message.has("text")) { String text = message.getString("text"); - if (text.startsWith("/")) { - if (user == null) sendMessage(chat_id, getInformation(WARNING_NO_USERNAME)); - else handleInput(chat_id, chatType.contains("group"), user, text); - } + if (text.startsWith("/") || text.startsWith("!")) handleInput(chat_id, chatType.contains("group"), user, text); + else handleText(chat_id, chatType.contains("group"), user, text); + return; } } @@ -216,11 +225,11 @@ public class Vylbot { sendMessage(chat_id, getInformation(COMMAND_HELP), PARSE_MARKDOWN); return; - case COMMAND_POLE: - sendMessage(chat_id, getInformation(WARNING_NOT_IMPLEMENTED)); + case COMMAND_TALIBOT_STATS: + case COMMAND_RANKING: + sendMessage(chat_id, chats.get(chat_id).getRanking()); return; - default: return; } } @@ -236,26 +245,49 @@ public class Vylbot { return; default: - sendMessage(chat_id, getInformation(WARNING_NO_GROUP)); return; } } - - /*private boolean exists(long chat_id, String user) { - return chats.containsKey(chat_id) && chats.get(chat_id).exists(user); - }*/ - - private String getPole(long chat_id, String user) { - - return "Congratulations " + user + ", you got the daily pole position! " + - "You win 200 pepes. Try again in 24 hours."; + private void handleText(long chat_id, boolean group, String user, String text) throws UnirestException { + if(text.toLowerCase().contains("pole")) { + if(group) { + if (user == null) sendMessage(chat_id, getInformation(WARNING_NO_USERNAME)); + else try { + sendMessage(chat_id, winPole(chat_id, user)); + } catch (PoleBlockedException e) { + return; + } + } + else sendMessage(chat_id, getInformation(WARNING_NO_GROUP)); + } } - /*private void saveChat(long chat_id) throws SaveErrorException { - Persistence.getInstance().saveChat(chat_id, chats.get(chat_id)); - chats.get(chat_id).setDirty(false); - }*/ + private boolean exists(long chat_id, String user) { + return chats.containsKey(chat_id) && chats.get(chat_id).exists(user); + } + + private String winPole(long chat_id, String user) throws PoleBlockedException { + if(!chats.containsKey(chat_id)) chats.put(chat_id, new Chat()); + if(!chats.get(chat_id).availablePole()) throw new PoleBlockedException(); + + try { + chats.get(chat_id).winPole(user); + saveChat(chat_id); + return "El usuario @" + user + " ha hecho la pole!"; + } catch (SaveErrorException e) { + return e.getMessage(); + } + } + + private void saveChat(long chat_id) throws SaveErrorException { + try { + Persistence.getInstance().saveChat(chat_id, chats.get(chat_id)); + } catch (SaveErrorException e) { + e.printStackTrace(); + throw e; + } + } private String getInformation(int command) { switch (command) { @@ -263,28 +295,12 @@ public class Vylbot { return "Hola. Soy el bot personal de Vylion."; case COMMAND_HELP: - return "Here is a list of the commands I accept:\n\n" + - "/register - Open a new vault in this chat under your name\n" + - "/newbet - Start the creation of a new bet. _*This will lock the " + - "bot in a bet creation until finished*_\n" + - "/done - While on a bet creation, it finishes it and asks you to " + - "designate the bet moderator. _*Only the bet creator can use " + - "this*_\n" + - "/checkbet - Shows the current state of the bet.\n" + - "/closebet - If there's a current active bet, it finishes it " + - "and let's you choose the outcome. _*Only the bet moderator " + - "can use this*_\n" + - "/cancelbet - If something went wrong, it let's you cancel a bet. " + - "_*Only the bet creator (during creation) or the bet moderator " + - "(if creation has finished) can use this*_\n" + - "/me - Tells your vault's contents.\n" + - "/give [username] [amount] - Let's you altruistically give money " + - "to another user.\n" + - "/ranking - Shows the top 5 richest players.\n" + - "\nRemember: this bot is geared towards group chats and you won't " + - "be able to use me in a one-on-one chat.\n" + - "Also, if I die during the creation of a bet, you can expect me " + - "not to remember it."; + return "Aquí tienes una lista de comandos que acepto:\n\n" + + "/start - Repite el saludo inicial\n" + + "/help - Saca esta lista\n" + + "/pole - Para hacer la pole diaria\n" + + "/ranking - Muestra la lista de poles conseguidas.\n" + + "\nEa."; case WARNING_UNKNOWN_ERROR: return "Algo ha ido MUY mal."; @@ -299,6 +315,9 @@ public class Vylbot { return "No tienes nombre de usuario. Regístrate con uno en la " + "configuración de Telegram para poder participar."; + case WARNING_POLE_BLOCKED: + return "La pole de hoy ya ha sido conseguida. Vuélvelo a intentar mañana."; + default: return "Entrada incorrecta."; } } @@ -311,8 +330,11 @@ public class Vylbot { case COMMAND_HELP: return commands.get(COMMAND_HELP); - case COMMAND_POLE: - return commands.get(COMMAND_POLE); + case COMMAND_RANKING: + return commands.get(COMMAND_RANKING); + + case COMMAND_TALIBOT_STATS: + return commands.get(COMMAND_TALIBOT_STATS); default: return "Entrada incorrecta."; }