List the files in a BitTorrent torrent with this quick Ruby script. Requires that you gem install bencode awesome_print before you run it.
#!/usr/bin/env ruby
#
# torrentdump - prints the contents of a torrent.
#
# Copyright (C) 2011 Paul Legato. All rights reserved.
# Licensed for personal, non-commercial use only.
# This code comes with NO WARRANTY, express or implied.
#
# Prerequisite gem setup:
# sudo gem install bencode awesome_print
#
require 'rubygems'
require 'bencode'
require 'awesome_print'
unless ARGV[0]
STDERR.puts <<END
Usage: torrentdump <filename> <-v>
If -v is given, prints the entire contents of the torrent except the binary "pieces" hash data.
If -vv is given, prints everything, including the binary hash data.
Otherwise, prints only the file list.
END
exit 1
end
# Method from http://stackoverflow.com/questions/3201890/is-there-an-elegant-way-to-remove-a-specific-key-from-a-hash-and-its-sub-hashes
def recursive_delete!(hash, to_remove)
hash.delete(to_remove)
hash.each_value do |value|
recursive_delete!(value, to_remove) if value.is_a? Hash
end
end
data = BEncode.load(File.read(ARGV[0]).force_encoding("binary"))
if ARGV[1] == "-vv"
ap data
elsif ARGV[1] == "-v"
recursive_delete!(data, "pieces")
ap data
else
if data["info"]["files"]
dir = data["info"]["name"] || ""
ap data["info"]["files"].map {|x| dir + "/" + x["path"].join("/") }
else
ap data["info"]["name"]
end
end
Ruby 1.9 imposes a character encoding on every string by default. This is fine for dealing with text, but caused errors in the BEncode library. (For some reason, the authors of BitTorrent chose to re-invent the wheel and developed their own binary encoding format.) We use the #force_encoding method on the torrent data to make Ruby treat the data as raw binary data and not try to interpret it.
They’re not “stories”. They’re tests. They don’t tuck you into bed with a glass of warm milk and a nice fairytale to dream about; they assert that certain things should happen and complain when they don’t, in a purely mechanical and precise way. We’re programming computers, machines of pure logic here, not reading to children. Let’s dispense with the pointless cutesy façade and focus precisely on the task at hand.
They don’t deliver what they promise, anyway. Frameworks like RSpec and Cucumber do not let you write tests in “plain English”. They let you write tests in a horrible chimeric programming language that adopts a superficial English-like veneer over top of what’s essentially a regular old unit testing framework.
It winds up giving you the benefits of neither English nor a well written testing API; your code simply becomes excessively verbose for the sake of a (highly fake and brittle) natural language veneer. You’re still highly restricted in what you can say, just like a regular old programming language. The set of Englishisms that you can use is so grossly restricted and precisely defined that you can’t think in anything remotely like English. You have to memorize a precise set of rigid, fixed English labels and use that and only that. You do get the verbosity of natural language, though, along with the restricted semantic domain of the API. You get the benefits of neither and the disadvantages of both.
Since you’re memorizing a highly restricted API anyway, skip the twee cruft and just use a short andprecise API from the start, without the pseudo-natural language clutter.
Custom dialog boxes are a must for any game. iPhone’s standard dialog boxes are fine for a business or productivity app, but in a game they look out of place. Users play games to escape from their everyday lives. Showing them the same exact graphic design that they associate with work and ordinary routine is a great way to subtly interrupt the immersiveness of their gameplay experience. We don’t want that, so we need to customize.
Cocos2d makes it easy to convert your drab standard UIAlertViews into glorious customized color dialog boxes. Above is an actual UIAlertView / custom dialog box transition from my upcoming iPhone game. Here’s how I did it. Continue Reading »
projectM (or its Windows-only predecessor, Milkdrop) can be used to make interesting visualizations for your music. Want to put your music on YouTube? You need to supply a video to accompany it. A projectM visualization makes an interesting and relatively easy accompaniment — far better than the typical static “picture of a CD cover” that most bands use:
This HowTo tells you what software you need and how to do it on your Mac. Continue Reading »
Android or iPhone? Which platform should I target first? iPhone, for now, though it’s close. Android cannot (yet) provide the same level of developer tools or paying user base, the Android emulator can’t handle graphics, and I already own an iPhone. I do expect that Android’s competitive position will improve significantly over the next few years, but it’s not there yet. Continue Reading »
Dell only provides certain PowerEdge BIOS flash upgrades in the form of Windows-only self-extracting archives (despite the facts that they claim to officially support Linux and that the BIOS flash utility itself is a DOS program.) Ordinary unzip won’t open the self-extracting archive. You need to run it on a Windows system, which I don’t have. Here’s how to flash your PowerEdge BIOS without Windows.
Dell provides the biosdisk utility to make a bootable FreeDOS image with the BIOS upgrade executable on it, but it doesn’t work with the Windows-only PowerEdge 4400 BIOS upgrade, since that won’t run on FreeDOS. They claim that biosdisk isn’t intended for PowerEdge systems, since they all have Linux BIOS flashes available; this does not seem to actually be the case for the 4400.
The Windows self-extractor does run under WINE, but it demands an actual floppy drive device to write to, which my computer doesn’t have. WINE also doesn’t seem to support mounting an image file as a floppy device, for some reason. You’ll need to use something like VMWare or a computer with a physical floppy drive to get this to extract itself.
Once you have a floppy image, here’s how to flash without biosdisk or Windows available: Continue Reading »
Now that we have implemented Black-Scholes in Clojure, let’s make a Swing GUI for it. The Swing GUI will have text boxes for all the necessary inputs, and calculate prices and Greeks when the button is pressed. It’s a simple and straightforward way to get started in Swing GUI programming in Clojure. Here’s what it looks like.
The GUI is written entirely in Clojure with the Swing toolkit. Calculation state is stored in a series of atoms. Watches are used to update the output table automatically when an atom changes, an idea from Kotka. I used the excellent MiG Layout for general layout functionality, and generic Swing widgets (JTextFields and a JTable) for the input and output. Continue Reading »
Clojure.contrib’s logging/spy macro is really useful for quick investigation of bugs with unclear stack traces, and to check that intermediate values in a calculation are being returned and composed correctly. Lazy sequences don’t get logged correctly, however:
> (log/spy [1 2 3 4 5])
[1 2 3 4 5] ;;; prints " [1 2 3 4 5] => [1 2 3 4 5]" to the log
> (log/spy (take 3 [1 2 3 4 5]))
(1 2 3) ;;; prints "(take 3 [1 2 3 4 5]) => clojure.lang.LazySeq@8592" to the log
The spy macro logs a string realization of the sequence per se, rather than its constituents. In the case of a concrete, fully realized sequence such as the literal vector in the first example, all values are known in advance, and the vector’s string realization in the log can helpfully be its actual contents. In the case of the lazy sequence returned by take, however, we get a less than helpful class name and some sort of instance identifier code rather than the actual contents of the sequence. A lazy sequence saves resources by merely promising to provide the values when asked. If they’re never asked for, they’re never computed. Since they haven’t been computed, they can’t be printed. A lazy sequence can also potentially be infinitely long, another good reason why they are not realized by default when converting the sequence to a string.
In our case, we don’t care about the resource usage, and we’re sure the sequence is finite. We want to force all values to be computed for manual inspection. (There are several ways of going about this.) The following modification of the spy macro converts the lazy sequence into a regular seq:
(defmacro lazy-spy
"Evaluates expr and outputs the form and its result to the debug log.
If the result is a lazy sequence, it is realized concretely in the log.
Returns the result of expr."
[expr]
`(let [a# ~expr] (log/log :debug (str '~expr " => "
(if (= clojure.lang.LazySeq (class a#))
(seq a#)
a#)))
a#))
This gives us:
> (lazy-spy (take 3 [1 2 3 4 5]))
(1 2 3) ;;; prints "(take 3 [1 2 3 4 5]) => (1 2 3)" to the log
Create a file called log4j.properties on your classpath and put the following into it:
# Based on the example properties given at http://logging.apache.org/log4j/1.2/manual.html
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern= %-5p %c - %m%n
That’s the short version. Read on for the gory details. Continue Reading »