package com.vdom.core;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.vdom.api.Card;
import com.vdom.api.GameEvent;
import com.vdom.api.GameEventListener;
@SuppressWarnings("serial")
public class UI extends JFrame implements GameEventListener {
// speed bar
// if no image, use text
static final String VP_TEXT = "VP: ";
static final String GAME_TYPE_TEXT = "Game: ";
static final String TURN_TEXT = "Turn: ";
float speedFactor = 100f;
boolean speedMax = false;
static String downloadSite;
public static final String[] downloadSiteDirs = new String[] { "common", "promo", "base", "intrigue", "seaside", "alchemy", "prosperity", };
public static int GAME_END_SLEEP = 300;
public static int TURN_END_SLEEP = 25;
public static int TURN_BEGIN_SLEEP = 10;
public static int PLAYING_ACTION_SLEEP = 5;
public static int ACTION_PLAYED_SLEEP = 5;
public static int COIN_PLAYED_SLEEP = 1;
public static int CARD_OBTAINED_SLEEP = 5;
public static int CARD_ADDED_TO_HAND_SLEEP = 1;
public static int CARD_REMOVED_FROM_HAND_SLEEP = 1;
public ConcurrentHashMap<String, ImageIcon> cardImages = new ConcurrentHashMap<String, ImageIcon>();
double imageScale = .53;
public File imagesDir;
public ImageIcon defaultImage;
public String defaultImageName = "blackmarket";
static final Dimension minimumSize = new Dimension(1, 400);
Game game;
JLabel turnLabel;
JLabel gameTypeLabel;
PlayerStats[] playerStats;
JPanel parentPanel;
JPanel handPanel;
JPanel playedPanel;
JPanel obtainedPanel;
public UI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void init(Game game) {
this.game = game;
setTitle("Dominion");
String tempDirString = System.getProperty("java.io.tmpdir");
File tempDir = new File(tempDirString);
imagesDir = new File(tempDir, "dominioncards");
if (downloadSite != null && !imagesDir.exists()) {
imagesDir.mkdirs();
downloadCards(downloadSite);
}
defaultImage = loadCardImage(defaultImageName);
if (defaultImage == null) {
System.err.println("Could not locate default image:" + imagesDir + "/" + defaultImageName + ".jpg");
System.exit(1);
}
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
parentPanel = new JPanel();
// BoxLayout boxLayout = new BoxLayout(parentPanel, BoxLayout.Y_AXIS);
// parentPanel.setLayout(boxLayout);
parentPanel.setLayout(new GridLayout(3, 1));
contentPane.add(parentPanel, BorderLayout.CENTER);
JPanel statsPanel = new JPanel(new GridLayout(1, Game.numPlayers + 2));
JPanel northPanel = new JPanel(new FlowLayout());
contentPane.add(northPanel, BorderLayout.NORTH);
northPanel.add(statsPanel);
JPanel gameStatsPanel = new JPanel(new GridLayout(3, 1));
gameStatsPanel.setBorder(new EmptyBorder(0, 10, 0, 10));
gameTypeLabel = new JLabel();
gameTypeLabel.setText(GAME_TYPE_TEXT + Game.gameType.toString());
turnLabel = new JLabel();
turnLabel.setText(TURN_TEXT + "1");
gameStatsPanel.add(gameTypeLabel);
gameStatsPanel.add(turnLabel);
statsPanel.add(gameStatsPanel);
playerStats = new PlayerStats[Game.numPlayers];
int i = 0;
for (Player player : Game.players) {
playerStats[i] = new PlayerStats(player);
playerStats[i].setBorder(new EmptyBorder(0, 10, 0, 10));
statsPanel.add(playerStats[i]);
i++;
}
// statsPanel.add(new JLabel(" "));
speedFactor = 190;
final JSlider speedSlider = new JSlider(1, 200, (int) speedFactor);
speedSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if (speedSlider.getValue() == 10) {
speedMax = true;
} else {
speedMax = false;
speedFactor = 201 - speedSlider.getValue();
}
}
});
statsPanel.add(speedSlider);
handPanel = new JPanel(new FlowLayout());
handPanel.setMinimumSize(minimumSize);
handPanel.setSize(minimumSize);
parentPanel.add(handPanel);
playedPanel = new JPanel(new FlowLayout());
playedPanel.setMinimumSize(minimumSize);
playedPanel.setSize(minimumSize);
parentPanel.add(playedPanel);
obtainedPanel = new JPanel(new FlowLayout());
obtainedPanel.setMinimumSize(minimumSize);
obtainedPanel.setSize(minimumSize);
parentPanel.add(obtainedPanel);
clearCardPanels();
setSize(1500, 870);
setVisible(true);
}
public void clear(JPanel panel) {
panel.removeAll();
// JLabel spacer = new JLabel("x");
// spacer.setMinimumSize(minimumSize);
// spacer.setSize(minimumSize);
// panel.add(spacer);
}
public void showHand(Player player) {
Card[] sortHand;
if (Game.sortCards) {
sortHand = player.hand.sort(new Util.CardHandComparator());
} else {
sortHand = player.hand.toArray();
}
clear(handPanel);
for (int i = 0; i < sortHand.length; i++) {
JLabel cardLabel = new JLabel();
cardLabel.setIcon(getCardIcon(sortHand[i]));
handPanel.add(cardLabel);
}
handPanel.revalidate();
handPanel.repaint();
}
public void addCardToPlayedPanel(Card card) {
JLabel cardLabel = new JLabel();
cardLabel.setIcon(getCardIcon(card));
playedPanel.add(cardLabel);
playedPanel.revalidate();
playedPanel.repaint();
}
public void addCardToObtainedPanel(Card card) {
JLabel cardLabel = new JLabel();
cardLabel.setIcon(getCardIcon(card));
obtainedPanel.add(cardLabel);
obtainedPanel.revalidate();
obtainedPanel.repaint();
}
public void clearCardPanels() {
clear(handPanel);
clear(playedPanel);
clear(obtainedPanel);
// parentPanel.revalidate();
handPanel.revalidate();
playedPanel.revalidate();
obtainedPanel.revalidate();
handPanel.repaint();
playedPanel.repaint();
obtainedPanel.repaint();
}
public ImageIcon getCardIcon(Card card) {
synchronized (cardImages) {
if (!cardImages.contains(card.getName())) {
ImageIcon cardImage = loadCardImage(card.getName());
if (cardImage == null) {
Util.debug("ERROR::::::::::::::::::::::::::::::::::::: Could not load image for:" + card.getName());
cardImages.put(card.getName(), defaultImage);
} else {
cardImages.put(card.getName(), cardImage);
}
}
}
return cardImages.get(card.getName());
}
public ImageIcon loadCardImage(String name) {
try {
File imageFile = new File(imagesDir, name + ".jpg");
if (!imageFile.exists()) {
StringBuilder sb = new StringBuilder();
for (char c : name.toCharArray()) {
if (Character.isLetter(c)) {
sb.append(c);
}
}
String fixedName = sb.toString().toLowerCase();
imageFile = new File(imagesDir, fixedName + ".jpg");
}
if (imageFile.exists() && imageFile.isFile() && imageFile.canRead()) {
ImageIcon icon = new ImageIcon(imageFile.getAbsolutePath());
Image img = icon.getImage();
Image newimg = img.getScaledInstance((int) (icon.getIconWidth() * imageScale), (int) (icon.getIconHeight() * imageScale),
java.awt.Image.SCALE_SMOOTH);
icon = new ImageIcon(newimg);
return icon;
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void updateTurn() {
turnLabel.setText(TURN_TEXT + game.turnCount);
}
public void gameEvent(GameEvent event) {
if (event.getType() == GameEvent.Type.TurnBegin) {
updateTurn();
for (int i = 0; i < playerStats.length; i++) {
playerStats[i].showTurnIndicator(i == Game.playersTurn);
}
// System.out.println("turn begin:" + event.getPlayer().getClass().getName());
showHand(Game.players[Game.playersTurn]);
sleep(TURN_BEGIN_SLEEP);
}
if (event.getType() == GameEvent.Type.TurnEnd) {
// update the vps to show any cards that were trashed by other players
for (PlayerStats stats : playerStats) {
stats.refreshVps();
}
// System.out.println("turn end:" + event.getPlayer().getClass().getName());
// showHand(Game.players[Game.playersTurn]);
sleep(TURN_END_SLEEP);
clearCardPanels();
}
if (event.getType() == GameEvent.Type.GameStarting) {
clearCardPanels();
}
if (event.getType() == GameEvent.Type.GameOver) {
clearCardPanels();
playedPanel.add(new JLabel("(Game Over)"));
playedPanel.revalidate();
playedPanel.repaint();
for (int i = 0; i < playerStats.length; i++) {
playerStats[i].showTurnIndicator(false);
}
sleep(GAME_END_SLEEP);
}
if ((event.getType() == GameEvent.Type.PlayingAction || event.getType() == GameEvent.Type.PlayingDurationAction)
&& event.getPlayer() == Game.players[Game.playersTurn]) {
// System.out.println("playing action:" + event.getCard().getName());
showHand(Game.players[Game.playersTurn]);
addCardToPlayedPanel(event.getCard());
sleep(PLAYING_ACTION_SLEEP);
}
if ((event.getType() == GameEvent.Type.PlayedAction) && event.getPlayer() == Game.players[Game.playersTurn]) {
// System.out.println("played action:" + event.getCard().getName());
showHand(Game.players[Game.playersTurn]);
sleep(ACTION_PLAYED_SLEEP);
}
if (event.getType() == GameEvent.Type.CardObtained && event.getPlayer() == Game.players[Game.playersTurn]) {
// System.out.println("obtaining card:" + event.getCard().getName());
playerStats[Game.playersTurn].refreshVps();
addCardToObtainedPanel(event.getCard());
sleep(CARD_OBTAINED_SLEEP);
}
if (event.getType() == GameEvent.Type.BuyingCard && event.getPlayer() == Game.players[Game.playersTurn]) {
sleep(CARD_OBTAINED_SLEEP / 2);
// System.out.println("obtaining card:" + event.getCard().getName());
playerStats[Game.playersTurn].refreshVps();
addCardToObtainedPanel(event.getCard());
sleep(CARD_OBTAINED_SLEEP);
}
if (event.getType() == GameEvent.Type.CardAddedToHand && event.getPlayer() == Game.players[Game.playersTurn]) {
// System.out.println("adding card:" + event.getCard().getName());
showHand(Game.players[Game.playersTurn]);
sleep(CARD_ADDED_TO_HAND_SLEEP);
}
if (event.getType() == GameEvent.Type.CardRemovedFromHand && event.getPlayer() == Game.players[Game.playersTurn]) {
// System.out.println("removing card:" + event.getCard().getName());
showHand(Game.players[Game.playersTurn]);
sleep(CARD_REMOVED_FROM_HAND_SLEEP);
}
if ((event.getType() == GameEvent.Type.PlayingCoin) && event.getPlayer() == Game.players[Game.playersTurn]) {
// System.out.println("playing coin:" + event.getCard().getName());
showHand(Game.players[Game.playersTurn]);
addCardToPlayedPanel(event.getCard());
sleep(COIN_PLAYED_SLEEP);
}
}
void downloadCards(String site) {
try {
if (!site.endsWith("/")) {
site = site + "/";
}
for (String s : downloadSiteDirs) {
String url = site + s;
String listPage = downloadUrlAsString(url);
if (!url.endsWith("/")) {
url = url + "/";
}
int at = 0;
while (at != -1) {
at = listPage.indexOf(".jpg\"", at);
if (at != -1) {
int start = listPage.lastIndexOf("\"", at);
int end = listPage.indexOf("\"", at);
String image = listPage.substring(start + 1, end);
File imageFile = new File(imagesDir, image);
Util.debug("downloading:" + url + image);
downloadUrlToFile(url + image, imageFile);
at = end;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
String downloadUrlAsString(String s) throws Exception {
InputStream is = null;
try {
StringBuilder sb = new StringBuilder();
URL u = new URL(s);
is = new BufferedInputStream(u.openStream());
int b;
while ((b = is.read()) != -1) {
sb.append((char) b);
}
return sb.toString();
} finally {
try {
is.close();
} catch (Exception e) {
// Ignore...
}
}
}
void downloadUrlToFile(String s, File file) throws Exception {
InputStream is = null;
OutputStream os = null;
try {
URL u = new URL(s);
is = new BufferedInputStream(u.openStream());
os = new BufferedOutputStream(new FileOutputStream(file));
int b;
while ((b = is.read()) != -1) {
os.write(b);
}
} finally {
try {
is.close();
} catch (Exception e) {
// Ignore...
}
try {
os.close();
} catch (Exception e) {
// Ignore...
}
}
}
void sleep(int time) {
try {
int sleepTime = 0;
if (speedMax) {
sleepTime = 1;
} else {
sleepTime = (int) (time * speedFactor);
}
Thread.sleep(sleepTime);
} catch (Exception e) {
e.printStackTrace();
}
}
static class PlayerStats extends JPanel {
Player player;
// JLabel winsLabel;
JLabel nameLabel;
JLabel vpLabel;
JLabel turnIndicator;
public PlayerStats(Player player) {
this.player = player;
setLayout(new GridLayout(3, 1));
// winsLabel = new JLabel();
// winsLabel.setText(WINS_TEXT + );
nameLabel = new JLabel();
nameLabel.setText(player.getPlayerName());
add(nameLabel);
vpLabel = new JLabel();
add(vpLabel);
turnIndicator = new JLabel("^^^^^^^");
add(turnIndicator);
refreshVps();
}
public void showTurnIndicator(boolean on) {
turnIndicator.setVisible(on);
}
public void refreshVps() {
vpLabel.setText(VP_TEXT + player.getVPs());
}
}
}