From 0465829c25ef43ba9ba898dff01ebaa5106fd1f8 Mon Sep 17 00:00:00 2001
From: Eduardo Pedroni <e.pedroni91@gmail.com>
Date: Fri, 5 Jun 2015 15:37:51 +0200
Subject: It works! Reading in a file, writing to the same file or a different
 existing file, glancing, perusing, adding and removing cards by number

---
 src/eu/equalparts/cardbase/data/Card.java          |   4 +-
 src/eu/equalparts/cardbase/data/CardBase.java      |  18 +-
 .../equalparts/cardbase/data/CardBaseManager.java  |  68 ++++++-
 src/eu/equalparts/cardbase/data/Deck.java          |  10 ++
 src/eu/equalparts/cardbase/data/MetaCardSet.java   |  31 +---
 src/eu/equalparts/cardbase/query/IO.java           |  46 ++++-
 src/eu/equalparts/cardbase/query/Test.java         |   1 -
 .../cardbase/standalone/CardBaseCLI.java           | 198 ++++++++++++++++++---
 8 files changed, 312 insertions(+), 64 deletions(-)

(limited to 'src')

diff --git a/src/eu/equalparts/cardbase/data/Card.java b/src/eu/equalparts/cardbase/data/Card.java
index 8e25d56..1bf6a75 100644
--- a/src/eu/equalparts/cardbase/data/Card.java
+++ b/src/eu/equalparts/cardbase/data/Card.java
@@ -28,8 +28,8 @@ public class Card {
 	public String border;
 	public String watermark;
 
-	// Not part of JSON, will be set later
+	// Not part of upstream JSON
 	public String setCode;
-	public String setName;
+	public Integer count;
 
 }
\ No newline at end of file
diff --git a/src/eu/equalparts/cardbase/data/CardBase.java b/src/eu/equalparts/cardbase/data/CardBase.java
index 70ae0ea..abdd423 100644
--- a/src/eu/equalparts/cardbase/data/CardBase.java
+++ b/src/eu/equalparts/cardbase/data/CardBase.java
@@ -4,9 +4,21 @@ import java.util.ArrayList;
 
 public class CardBase {
 
-	private ArrayList<Card> cards;
-	private ArrayList<Deck> decks;
-	
+	public ArrayList<Card> cards = new ArrayList<>();
+	public ArrayList<Deck> decks = new ArrayList<>();
 	
+	/**
+	 * @param setCode
+	 * @param number 
+	 * @return the card if found, else null.
+	 */
+	public Card getCardByNumber(String setCode, String number) {
+		for (Card card : cards) {
+			if (card.setCode.equals(setCode) && card.number.equals(number))
+				return card;
+		}
+		
+		return null;
+	}
 	
 }
diff --git a/src/eu/equalparts/cardbase/data/CardBaseManager.java b/src/eu/equalparts/cardbase/data/CardBaseManager.java
index acf5a3a..0baf9d7 100644
--- a/src/eu/equalparts/cardbase/data/CardBaseManager.java
+++ b/src/eu/equalparts/cardbase/data/CardBaseManager.java
@@ -2,6 +2,7 @@ package eu.equalparts.cardbase.data;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Iterator;
 
 import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.databind.JsonMappingException;
@@ -11,19 +12,17 @@ import eu.equalparts.cardbase.query.IO;
 public class CardBaseManager {
 	
 	private ArrayList<MetaCardSet> metaSets;
+	public CardBase cardBase;
 
-	public static void main(String... args) {
-		
-	}
-	
 	/**
 	 * Parse a cardbase file and create an associated CardBase object.
 	 * @throws IOException 
 	 * @throws JsonMappingException 
 	 * @throws JsonParseException 
 	 */
-	public CardBaseManager(File cardbase) throws JsonParseException, JsonMappingException, IOException {
+	public CardBaseManager(File cardBaseFile) throws JsonParseException, JsonMappingException, IOException {
 		metaSets = IO.getAllMetaSets();
+		cardBase = IO.readCardBase(cardBaseFile);
 	}
 
 	/**
@@ -34,10 +33,69 @@ public class CardBaseManager {
 	 */
 	public CardBaseManager() throws JsonParseException, JsonMappingException, IOException {
 		metaSets = IO.getAllMetaSets();
+		cardBase = new CardBase();
 	}
 	
 	public ArrayList<MetaCardSet> getAllMetaSets() {
 		return metaSets;
 	}
 	
+	/**
+	 * Add a specific amount of a card to the cardbase.
+	 * If the card is not already in the cardbase, it is added.
+	 * If it is already present, the count is simply updated.
+	 * 
+	 * 
+	 * @param newCard
+	 * @param count
+	 */
+	public void addCard(Card newCard, Integer count) {
+		Card card = cardBase.getCardByNumber(newCard.setCode, newCard.number);
+		if (card != null) {
+			card.count += count;
+		} else {
+			newCard.count = count;
+			cardBase.cards.add(newCard);
+		}
+	}
+
+	/**
+	 * Remove a specific amount of a card from the cardbase.
+	 * If the card is not present in the cardbase, nothing happens.
+	 * If the card is present in the card, the specified amount is removed.
+	 * If that amount is equal to or exceeds the count already in the cardbase,
+	 * the card entry is removed altogether. 
+	 * 
+	 * @param remove
+	 * @param count
+	 */
+	public void removeCard(Card remove, Integer count) {
+		Card card = cardBase.getCardByNumber(remove.setCode, remove.number);
+		if (card != null) {
+			if (card.count <= count) {
+				cardBase.cards.remove(card);
+			} else {
+				card.count -= count;
+			}
+		}
+	}
+	
+	/**
+	 * @return an iterator to the cards in the cardbase.
+	 */
+	public Iterator<Card> cardIterator() {
+		return cardBase.cards.iterator();
+	}
+
+	/**
+	 * Return a card from the cardBase by setCode and number.
+	 * If no such card is in the cardbase, return null.
+	 * 
+	 * @param code
+	 * @param string
+	 * @return
+	 */
+	public Card getCard(String code, String number) {
+		return cardBase.getCardByNumber(code, number);
+	}
 }
diff --git a/src/eu/equalparts/cardbase/data/Deck.java b/src/eu/equalparts/cardbase/data/Deck.java
index 50f1129..b5fe402 100644
--- a/src/eu/equalparts/cardbase/data/Deck.java
+++ b/src/eu/equalparts/cardbase/data/Deck.java
@@ -1,5 +1,15 @@
 package eu.equalparts.cardbase.data;
 
+import java.util.HashMap;
+
 public class Deck {
 
+	/**
+	 * Cards stored in key-value pairs of [multiverse ID, amount].
+	 */
+	public HashMap<Integer, Integer> cards;
+	
+	public Deck() {
+		
+	}
 }
diff --git a/src/eu/equalparts/cardbase/data/MetaCardSet.java b/src/eu/equalparts/cardbase/data/MetaCardSet.java
index 4ddf228..3b7d4fd 100644
--- a/src/eu/equalparts/cardbase/data/MetaCardSet.java
+++ b/src/eu/equalparts/cardbase/data/MetaCardSet.java
@@ -2,34 +2,9 @@ package eu.equalparts.cardbase.data;
 
 public class MetaCardSet {
 
-	private String name = "";
-	private String code = "";
-	private String releaseDate = "";
-	
-	
-	public String getName() {
-		return name;
-	}
-	
-	public void setName(String name) {
-		this.name = name;
-	}
-	
-	public String getCode() {
-		return code;
-	}
-	
-	public void setCode(String code) {
-		this.code = code;
-	}
-	
-	public String getReleaseDate() {
-		return releaseDate;
-	}
-	
-	public void setReleaseDate(String releaseDate) {
-		this.releaseDate = releaseDate;
-	}
+	public String name = "";
+	public String code = "";
+	public String releaseDate = "";
 	
 	@Override
 	public String toString() {
diff --git a/src/eu/equalparts/cardbase/query/IO.java b/src/eu/equalparts/cardbase/query/IO.java
index 65a3a34..9b81b20 100644
--- a/src/eu/equalparts/cardbase/query/IO.java
+++ b/src/eu/equalparts/cardbase/query/IO.java
@@ -2,6 +2,7 @@ package eu.equalparts.cardbase.query;
 
 import java.io.File;
 import java.io.IOException;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 
@@ -21,21 +22,56 @@ public class IO {
 	public static final String BASE_URL = "http://mtgjson.com/json/";
 	public static final String SETS_URL = BASE_URL + "SetList.json";
 	
-	private static final ObjectMapper mapper = new ObjectMapper();
+	private static final ObjectMapper mapper = createMapper();
 
-	public static CardSet getCardSet(String setId) {
-		return new CardSet();
+	private static ObjectMapper createMapper() {
+		ObjectMapper om = new ObjectMapper();
+		om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+		return om;
 	}
 	
-	public static ArrayList<MetaCardSet> getAllMetaSets() throws JsonParseException, JsonMappingException, IOException {
-		//mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);		
+	/**
+	 * @param code
+	 * @return the actual cardset (containing cards).
+	 * @throws IOException 
+	 * @throws MalformedURLException 
+	 * @throws JsonMappingException 
+	 * @throws JsonParseException 
+	 */
+	public static CardSet getCardSet(String code) throws JsonParseException, JsonMappingException, MalformedURLException, IOException {
+		return mapper.readValue(new URL(BASE_URL + code + ".json"), CardSet.class);
+	}
+	
+	/**
+	 * @return a list of metadata for every available set.
+	 * @throws JsonParseException
+	 * @throws JsonMappingException
+	 * @throws IOException
+	 */
+	public static ArrayList<MetaCardSet> getAllMetaSets() throws JsonParseException, JsonMappingException, IOException {	
 		return mapper.readValue(new URL(SETS_URL), new TypeReference<ArrayList<MetaCardSet>>() {});
 	}
 	
+	/**
+	 * @param file
+	 * @return a CardBase object equivalent to the given file.
+	 * @throws JsonParseException
+	 * @throws JsonMappingException
+	 * @throws IOException
+	 */
 	public static CardBase readCardBase(File file) throws JsonParseException, JsonMappingException, IOException {
 		return mapper.readValue(file, CardBase.class);
 	}
 	
+	/**
+	 * Writes the provided CardBase to the provided file in JSON format.
+	 * 
+	 * @param file
+	 * @param cardBase
+	 * @throws JsonGenerationException
+	 * @throws JsonMappingException
+	 * @throws IOException
+	 */
 	public static void writeCardBase(File file, CardBase cardBase) throws JsonGenerationException, JsonMappingException, IOException {
 		mapper.writeValue(file, cardBase);
 	}
diff --git a/src/eu/equalparts/cardbase/query/Test.java b/src/eu/equalparts/cardbase/query/Test.java
index 2050c76..e466c55 100644
--- a/src/eu/equalparts/cardbase/query/Test.java
+++ b/src/eu/equalparts/cardbase/query/Test.java
@@ -59,7 +59,6 @@ public class Test {
 		for (CardSet set : sets.values()) {
 			for (Card card : set.cards) {
 				card.setCode = set.code;
-				card.setName = set.name;
 				// System.out.println(set.getName() + ": " + card.getName());
 
 				allCards.add(card);
diff --git a/src/eu/equalparts/cardbase/standalone/CardBaseCLI.java b/src/eu/equalparts/cardbase/standalone/CardBaseCLI.java
index 2806a9e..d0503ac 100644
--- a/src/eu/equalparts/cardbase/standalone/CardBaseCLI.java
+++ b/src/eu/equalparts/cardbase/standalone/CardBaseCLI.java
@@ -4,22 +4,32 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Scanner;
 
 import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.databind.JsonMappingException;
 
+import eu.equalparts.cardbase.data.Card;
 import eu.equalparts.cardbase.data.CardBaseManager;
+import eu.equalparts.cardbase.data.CardSet;
 import eu.equalparts.cardbase.data.MetaCardSet;
+import eu.equalparts.cardbase.query.IO;
 
 /**
  * This provides a lightweight CLI for interacting with cardbase files. 
  * 
  */
 public class CardBaseCLI {
-	
-	private static String selectedSet = "";
+
+	private static CardSet selectedSet = null;
+	private static HashMap<String, CardSet> setCache = new HashMap<String, CardSet>();
 	private static CardBaseManager cbm;
 	private static boolean exit = false;
+	private static String help = "No help file was found";
+	private static File cardBaseFile;
 
 	/**
 	 * Execute the interface.
@@ -33,18 +43,35 @@ public class CardBaseCLI {
 		try {
 			// construct the cardbase
 			if (args.length > 0) {
-				System.out.println("Building cardbase from " + args[0]);
-				cbm = new CardBaseManager(new File(args[0]));
+				cardBaseFile = new File(args[0]);
+				if (cardBaseFile.exists() && cardBaseFile.isFile() && cardBaseFile.canRead()) {
+					System.out.println("Loading cardbase from " + args[0]);
+					cbm = new CardBaseManager(cardBaseFile);
+				} else {
+					System.out.println(args[0] + " appears to be invalid");
+					System.exit(0);
+				}
 			} else {
-				System.out.println("No cardbase file was provided, initialising a clean cardbase");
-				cbm = new CardBaseManager();
+				//System.out.println("No cardbase file was provided, initialising a clean cardbase");
+				System.out.println("Loading testbase for debugging purposes");
+				cardBaseFile = new File("testbase");
+				cbm = new CardBaseManager(cardBaseFile);
 			}
 
 			// initialise necessary components
 			System.out.println("Fetching card sets from upstream");
 			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 
+			System.out.println("Loading externals");
+			File helpFile = new File("help");
+			if (helpFile.exists() && helpFile.canRead()) {
+				help = new Scanner(helpFile).useDelimiter("\\Z").next();
+			} else {
+				System.out.println("Help file is not available, I hope you know how to use the program!");
+			}
+			
 			while (!exit) {
+				System.out.print(selectedSet == null ? "> " : selectedSet.code + " > ");
 				String rawInput = br.readLine().trim().toLowerCase();
 				String[] commands = rawInput.split("[ \t]+");
 
@@ -64,21 +91,51 @@ public class CardBaseCLI {
 
 	}
 
-	private static void parse(String[] commands) {
+	private static void parse(String[] commands) throws JsonParseException, JsonMappingException, MalformedURLException, IOException {
 		if (commands.length > 0) {
 			switch (commands[0]) {
 			/*
-			 * Exit procedures
+			 * Show help
 			 */
-			case "exit":
-				exit = true;
+			case "help":
+				System.out.println(help);
 				break;
+			
 			/*
-			 * Show help (externalised?) 
+			 * Write current CardBase to file
 			 */
-			case "help":
-				System.out.println("google it");
+			case "write":
+				if (commands.length > 1) {
+					File output = new File(commands[1]);
+					if (output.exists()) {
+						if(output.isFile()) {
+							if (output.canWrite()) {
+								IO.writeCardBase(output, cbm.cardBase);
+								cardBaseFile = output;
+								System.out.println("Cardbase saved to " + output.getAbsolutePath());
+							} else {
+								System.out.println(commands[1] + " cannot be written to, nothing was written");
+							}
+						} else {
+							System.out.println(commands[1] + " is not a file, nothing was written");
+						}
+					} else {
+						System.out.println(commands[1] + " does not exist, nothing was written");
+					}
+				} else if (cardBaseFile != null) {
+					System.out.println("Writing to " + cardBaseFile.getAbsolutePath());
+				} else {
+					System.out.println("Please provide a file name");
+				}
 				break;
+
+			/*
+			 * Exit procedures
+			 */
+			case "exit":
+				exit = true;
+				break;
+
 			/*
 			 * Print a list of valid set codes
 			 */
@@ -87,31 +144,132 @@ public class CardBaseCLI {
 					System.out.println(mcs);
 				}
 				break;
+
 			/*
 			 * Select a set, any card numbers provided will be fetched from that set
 			 */
 			case "set":
 				for (MetaCardSet mcs : cbm.getAllMetaSets()) {
-					if (mcs.getCode().equalsIgnoreCase(commands[1])) {
-						System.out.println("Selected set: " + mcs.getName());
-						selectedSet = mcs.getCode();
+					if (mcs.code.equalsIgnoreCase(commands[1])) {
+						// if the set is cached, use that
+						if (setCache.containsKey(mcs.code)) {
+							selectedSet = setCache.get(mcs.code);
+						} else {
+							selectedSet = IO.getCardSet(mcs.code);
+							setCache.put(mcs.code, selectedSet);
+						}
+						System.out.println("Selected set: " + mcs.name);
 						return;
 					}
 				}
 				System.out.println(commands[1] + " does not correspond to any set (use \"sets\" to see all valid set codes)");
 				break;
+				
 			/*
-			 * Write current CardBase to file
+			 * Print a brief list of the complete cardbase.
 			 */
-			case "write":
+			case "glance":
+				for (Iterator<Card> i = cbm.cardIterator(); i.hasNext();) {
+					printGlance(i.next());
+				}
+				break;
+			
+			/*
+			 * Print a detailed information of a single card or the whole cardbase.
+			 */
+			case "peruse":
+				if (commands.length > 1) {
+					if (selectedSet != null) {
+						Card card = cbm.getCard(selectedSet.code, commands[1]);
+						if (card != null) {
+							printPerusal(card);
+						} else {
+							System.out.println("Card not in cardbase");
+						}
+					} else {
+						System.out.println("Please select a set before perusing a specific card");
+					}
+				} else {
+					for (Iterator<Card> i = cbm.cardIterator(); i.hasNext();) {
+						printPerusal(i.next());
+					}
+				}
+				break;
+				
+			/*
+			 * Remove one or more cards
+			 */
+			case "remove":
+				if (selectedSet != null) {
+					if (commands.length > 1) {
+						Card remove = selectedSet.getCardByNumber(commands[1]);
+						if (remove != null) {
+							Integer count = 1;
+							if (commands.length > 2 && commands[2].matches("[0-9]+")) {
+								count = Integer.valueOf(commands[2]);
+								if (count <= 0) {
+									System.out.println("Can't remove " + count + " cards");
+									return;
+								}
+							}
+							cbm.removeCard(remove, count);
+							System.out.println("Removed " + count + "x " + remove.name);
+						} else {
+							System.out.println(commands[1] + " does not correspond to a card in " + selectedSet.name);
+						}
+					} else {
+						System.out.println("Please specify a card number to remove");
+					}
+				} else {
+					System.out.println("Select a set before removing cards.");
+				}
 				break;
+				
 			/*
-			 * Try to parse a card number and get it from the set
+			 * Add one or more cards
 			 */
 			default:
+				if (selectedSet != null) {
+					Card newCard = selectedSet.getCardByNumber(commands[0]);
+					if (newCard != null) {
+						Integer count = 1;
+						if (commands.length > 1 && commands[1].matches("[0-9]+")) {
+							count = Integer.valueOf(commands[1]);
+							if (count <= 0) {
+								System.out.println("Can't add " + count + " cards");
+								return;
+							}
+						}
+						newCard.setCode = selectedSet.code;
+						cbm.addCard(newCard, count);
+						System.out.println("Added " + count + "x " + newCard.name);
+					} else {
+						System.out.println(commands[0] + " does not correspond to a card in " + selectedSet.name);
+					}
+				} else {
+					System.out.println("Select a set before adding cards.");
+				}
 				break;
 			}
 		}
 	}
-
+	
+	private static void printPerusal(Card card) {
+		printGlance(card);
+		if (card.type != null) System.out.println("\t" + card.type);
+		if (card.manaCost != null) System.out.println("\tCost: " + card.manaCost);
+		if (card.power != null && card.toughness != null) System.out.println("\t" + card.power + "/" + card.toughness);
+		if (card.loyalty != null) System.out.println("\tLoyalty: " + card.loyalty);
+		
+		if (card.text != null) System.out.println("\t" + card.text.replaceAll("\n", "\n\t"));
+		if (card.flavor != null) System.out.println("\t" + card.flavor.replaceAll("\n", "\n\t"));
+		
+		if (card.rarity != null) System.out.println("\t" + card.rarity);
+		if (card.multiverseid != null) System.out.println("\tMID: " + card.multiverseid);
+		if (card.artist != null) System.out.println("\tIllus. " + card.artist);
+	}
+	
+	private static void printGlance(Card card) {
+		System.out.println(String.format("%1$-4d %2$s (%3$s, %4$s)", card.count, card.name, card.setCode, card.number));
+	}
 }
-- 
cgit v1.2.3