December 2010 Archives

The Theory of Poker

| | TrackBacks (0)

As previously noted, I don't have a good track record with online poker. I resolved that before playing again (since I still have a little money online) I would read David Sklansky's The Theory of Poker (published by 2+2) through twice, take notes and write a review. Hopefully somewhere in that process some poker knowledge has seeped into my cerebrum.

The Theory of Poker was first published in 1987, long before the domination of No Limit Texas Hold'em in televised poker and the subsequent poker boom. Thus it doesn't focus on any particular form of poker, instead providing examples from various types of the game. Having said that, in my reading I concentrated on advice applicable to online Hold'em, as that is what I play.

The Theory of Poker

Iminra

| | TrackBacks (0)

Over a year ago I wrote here about a library I had written to work out the implied interest rates available on Intrade. This library was originally envisioned as a cloud application built on top of the Google App Engine, but I couldn't get it working on that platform. I recently tried again and now it works! The application is called Iminra - Implied Interest Rates on Intrade.

For a project, I needed to cut, copy and paste from a Java JTable to Excel. The KeyAdapter I ended up writing is below. As it turns out, there is another similar version online from 1999 at Javaworld (I borrowed the contiguous block check from this code, as I hadn't previously considered that possibility) - but I like mine better.

To copy to Excel, a Java program must put the data onto the clipboard in a format Excel understands. The easiest way to do this is to use a String, structured as a series of cells separated by tabs and rows separated by line breaks. To read in data Excel puts on the clipboard, is just a matter of parsing a similarly structured String. There are other data formats available on the clipboard, but just using plain text is all that was needed for my requirements. However if you need to escape tabs and line breaks in your data then it might be worth investigating them. The code below just converts tabs and line breaks to spaces when copying to the clipboard, and ignore them when reading in (as tabs can't be in an Excel cell and I couldn't see how to detect line breaks in a cell rather than separating lines). To use this class just add it as a KeyListener on the table (JTable.addKeyLisenter).

 
package com.cordinc.util.gui;

import java.awt.Toolkit; 
import java.awt.datatransfer.Clipboard; 
import java.awt.datatransfer.DataFlavor; 
import java.awt.datatransfer.StringSelection; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent;

import javax.swing.JOptionPane; 
import javax.swing.JTable;

/** 
 * KeyAdapter to detect Windows standard cut, copy and paste keystrokes on a JTable and put them to the clipboard 
 * in Excel friendly plain text format. Assumes that null represents an empty column for cut operations. 
 * Replaces line breaks and tabs in copied cells to spaces in the clipboard. 
 * 
 * @see java.awt.event.KeyAdapter 
 * @see javax.swing.JTable 
 */ 
public class ClipboardKeyAdapter extends KeyAdapter {

        private static final String LINE_BREAK = "\n"; 
        private static final String CELL_BREAK = "\t"; 
        private static final Clipboard CLIPBOARD = Toolkit.getDefaultToolkit().getSystemClipboard(); 
        
        private final JTable table; 
        
        public ClipboardKeyAdapter(JTable table) { 
                this.table = table; 
        } 
        
        @Override 
        public void keyReleased(KeyEvent event) { 
                if (event.isControlDown()) { 
                        if (event.getKeyCode()==KeyEvent.VK_C) { // Copy                        
                                cancelEditing(); 
                                copyToClipboard(false); 
                        } else if (event.getKeyCode()==KeyEvent.VK_X) { // Cut 
                                cancelEditing(); 
                                copyToClipboard(true); 
                        } else if (event.getKeyCode()==KeyEvent.VK_V) { // Paste 
                                cancelEditing(); 
                                pasteFromClipboard();           
                        } 
                } 
        } 
        
        private void copyToClipboard(boolean isCut) { 
                int numCols=table.getSelectedColumnCount(); 
                int numRows=table.getSelectedRowCount(); 
                int[] rowsSelected=table.getSelectedRows(); 
                int[] colsSelected=table.getSelectedColumns(); 
                if (numRows!=rowsSelected[rowsSelected.length-1]-rowsSelected[0]+1 || numRows!=rowsSelected.length || 
                                numCols!=colsSelected[colsSelected.length-1]-colsSelected[0]+1 || numCols!=colsSelected.length) {

                        JOptionPane.showMessageDialog(null, "Invalid Copy Selection", "Invalid Copy Selection", JOptionPane.ERROR_MESSAGE);
                        return; 
                } 
                
                StringBuffer excelStr=new StringBuffer(); 
                for (int i=0; i<numRows; i++) { 
                        for (int j=0; j<numCols; j++) { 
                                excelStr.append(escape(table.getValueAt(rowsSelected[i], colsSelected[j]))); 
                                if (isCut) { 
                                        table.setValueAt(null, rowsSelected[i], colsSelected[j]); 
                                } 
                                if (j<numCols-1) { 
                                        excelStr.append(CELL_BREAK); 
                                } 
                        } 
                        excelStr.append(LINE_BREAK); 
                } 
                
                StringSelection sel  = new StringSelection(excelStr.toString()); 
                CLIPBOARD.setContents(sel, sel); 
        } 
        
        private void pasteFromClipboard() { 
                int startRow=table.getSelectedRows()[0]; 
                int startCol=table.getSelectedColumns()[0];

                String pasteString = ""; 
                try { 
                        pasteString = (String)(CLIPBOARD.getContents(this).getTransferData(DataFlavor.stringFlavor)); 
                } catch (Exception e) { 
                        JOptionPane.showMessageDialog(null, "Invalid Paste Type", "Invalid Paste Type", JOptionPane.ERROR_MESSAGE);
                        return; 
                } 
                
                String[] lines = pasteString.split(LINE_BREAK); 
                for (int i=0 ; i<lines.length; i++) { 
                        String[] cells = lines[i].split(CELL_BREAK); 
                        for (int j=0 ; j<cells.length; j++) { 
                                if (table.getRowCount()>startRow+i && table.getColumnCount()>startCol+j) { 
                                        table.setValueAt(cells[j], startRow+i, startCol+j); 
                                } 
                        } 
                } 
        } 
        
        private void cancelEditing() { 
                if (table.getCellEditor() != null) { 
                        table.getCellEditor().cancelCellEditing(); 
            } 
        } 
        
        private String escape(Object cell) { 
                return cell.toString().replace(LINE_BREAK, " ").replace(CELL_BREAK, " "); 
        } 
} 

The Arts Past and Present: Mosaics

| | TrackBacks (0)

Available on iTunes or OU Podcasts

Part of an introductory unit on art, this Open University series consists of 8 podcasts on Roman mosaics, focusing exclusively on those found at Brading Villa on the Isle of Wight in Britain. All episodes come with PDF transcripts. The series starts with two introductory podcasts (one audio and one video), followed by 5 video podcasts each of which examines a particular mosaic at the villa. The final episode is an audio only meta discussion on what the series was aiming to achieve. The 5 mosaic podcasts are all around 3 minutes long and 30MB in size (recorded at 320×240 resolution).

The series is presented by a classicist, archaeologist and a mosaic artist (sounds like the start of a joke). The episodes see them sitting or standing next to the mosaic they are about to discuss, with each bringing their own view on the context, story or construction of the artwork. The time the were made mosaics is never actually mentioned, but they do mention that the unique cockheaded man mosaic may be a caricature of the Emperor Gallus (his name meaning cockerel in Latin) - which dates it to the 3rd century AD. While the cockheaded man is not seen anywhere else, most of the mosaics depict common scenes found throughout the Roman world. The suggestion is that the artists had a pattern book or brochure from which clients selected their mosaics.

Only for people especially interested in mosaics.