iTunes Song Rating with Logitech G15 G-Keys and Python
I just put together a quick script for setting song ratings in iTunes using a Logitech G15 keyboard and the programmable “G-keys” For this to work, you’ll need Python (I’m using 2.7) and the pywin32 package (http://sourceforge.net/projects/pywin32/)
import win32com.client
import sys
itunes = win32com.client.gencache.EnsureDispatch("iTunes.Application")
itunes.CurrentTrack.Rating = int(sys.argv[1]) * 20
Put this in a script somewhere easy to remember. Then, open up the Logitech Key Profiler, and for each G-key, set it up as such (example is the first G-key):
G1 -> Assign Shortcut
Name: Whatever you want. I used Rate 1
Shortcut: pythonw itunes_rate.py 1
Working Directory: ##Location of your script if you don’t want to enter the entire path to the script##
Just do that and you should be good to go. Another thing to note is that I have the Python directory in my environment path. The version pythonw lets Python execute without bringing up a command prompt window, which gets annoying and might interrupt you if you’re playing a game or something.
iTunes Playcount Updater Using Last.fm
This script takes your Last.fm username, finds your playcounts for tracks in your iTunes library, and updates those playcounts. Useful if you base playlists off of how much you listen to a particular song and you need to keep your playcounts in sync from various sources.
#
# iTunes Playcount Updater
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
#
# INSTRUCTIONS:
# ----------------------------------------------------------------------------
# This script downloads your Last.FM play history and updates the playcount
# for all tracks it can find in your library. There are two modes, one which uses
# currently selected tracks, and the other which searches your entire Last.fm
# library
#
# Requirements:
# pywin32
# BeautifulSoup
#Strange or International characters will be either replaced or removed. Map them here
strangeCharacterMap = ({
u"\u042f" : "r" #Korn's crazy R
})
import sys
import win32com.client
import urllib
from BeautifulSoup import BeautifulSoup
import unicodedata
import time
lastFMUrl = "http://ws.audioscrobbler.com/2.0/?method="
apiKey = "YOUR_API_KEY"
itunes = None
username = ""
def getTracks(page):
url = lastFMUrl + "library.gettracks&api_key=" + apiKey + "&user=" + username + "&page=" + str(page)
data = urllib.urlopen(url).read()
soup = BeautifulSoup(data)
totalpages = int(soup.find("tracks")["totalpages"])
tracks_soup = soup.findAll("track")
tracks = {}
for t in tracks_soup:
name = t.find("name").next.replace("&", "&").replace(""", "\"")
artist = t.find("artist").find("name").next.replace("&", "&").replace(""", "\"")
plays = int(t.find("playcount").next)
tracks[artist + " " + name] = [artist, name, plays]
return (tracks, totalpages)
def check_users_library():
libraryPlaylist = itunes.LibraryPlaylist
page = 0
tracks, pages = getTracks(1)
while page < pages:
page = page + 1
tracks, x = getTracks(page)
print "Page: " + str(page) + " / " + str(pages)
for track in tracks:
search = libraryPlaylist.Search(track, 1)
if search == None:
continue
else:
for x in search:
if x.Artist.lower() == tracks[track][0].lower() and x.Name.lower() == tracks[track][1].lower():
x.PlayedCount = tracks[track][2]
def check_selected_tracks():
selectedTracks = itunes.SelectedTracks
for t in selectedTracks:
last_access = time.clock()
url = ""
try:
url = lastFMUrl + "track.getInfo&api_key=" + apiKey + "&username=" + username + "&artist=" + \
urllib.quote(unicodedata.normalize("NFKD", t.Artist).encode("ascii", "ignore")) + \
"&track=" + urllib.quote(unicodedata.normalize("NFKD", t.Name).encode("ascii", "ignore")) + "&autocorrect=1"
except:
print "Problem creating URL for " + t.Artist + " - " + t.Name
continue
data = urllib.urlopen(url).read()
soup = BeautifulSoup(data)
playcount = soup.find("userplaycount")
if playcount == None:
print "No plays for " + t.Artist + " - " + t.Name
else:
t.PlayedCount = int(playcount.next)
print t.Artist + " - " + t.Name + " played " + str(t.PlayedCount) + " times"
while time.clock() - last_access < 1.0:
pass
def main():
global username
global itunes
username = raw_input("Last.FM Username: ")
itunes = win32com.client.gencache.EnsureDispatch("iTunes.Application")
print
print "Use mode:"
mode = raw_input("1 = Check selected tracks\n2 = Check entire Last.fm library\n")
if mode == "1":
check_selected_tracks()
elif mode == "2":
check_users_library()
else:
pass
if __name__ == "__main__":
main()
print "Completed"
Linear Approximation for S-Boxes
Based off of tutorial by Howard M. Heys
import pprint
"""
input 0 1 2 3 4 5 6 7 8 9 A B C D E F
output 8 4 2 1 C 6 3 D A 5 E 7 F B 9 0
"""
inp = ["0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"]
out = ["1000", "0100", "0010", "0001", "1100", "0110", "0011", "1101", "1010", "0101", "1110", "0111", "1111", "1011", "1001", "0000"]
# S-Box from Heys tutorial
#out = ["1110", "0100", "1101", "0001", "0010", "1111", "1011", "1000", "0011", "1010", "0110", "1100", "0101", "1001", "0000", "0111"]
def check_bits(inbits, outbits):
total = 0
for x in range(len(inp)):
r = 0
for a in inbits:
r ^= int(inp[x][a])
for b in outbits:
r ^= int(out[x][b])
if r == 0:
total += 1
return total
def linear_approximation():
result = []
for i in range(len(inp)):
row = []
for j in range(len(inp)):
inbits = []
outbits = []
for x in range(len(inp[i])):
if inp[i][x] == "1":
inbits.append(x)
for x in range(len(inp[j])):
if inp[j][x] == "1":
outbits.append(x)
row.append(check_bits(inbits, outbits) - 8)
result.append(row)
return result
if __name__ == '__main__':
pp = pprint.PrettyPrinter()
pp.pprint(linear_approximation())
Miller-Rabin Error Testing
This program brute force tests the Miller-Rabin algorithm to determine error probabilities. For the assignment, we ran it from 101,000 to 102,000. The program runs in about 25 minutes.
import sys, time
#Runs the algorithm for some values n and a. m and k are already calculated
def miller_rabin(n, a, m, k):
#pow(x, y, z) = x^y mod z
b = pow(a, m, n)
#b is congruent to 1 (mod n)
if b == 1:
return (True, n, a, m, k, b) #Prime
for i in xrange(0, k):
#b is congruent to -1 (mod n)
if b == n - 1:
return (True, n, a, m, k, b) #Prime
else:
b = (b * b) % n
return (False, n, a, m, k, b) #Composite
#Performs the overall loop and saves the data to a file
def miller_time():
start = time.clock()
f = open("stats.txt", "a")
for n in xrange(101000, 102001):
print n
primes = 0
composites = 0
m = n - 1
k = 0
#Calculate k and m
while m % 2 == 0:
m >>= 1
k += 1
for a in xrange(1, n):
ret = miller_rabin(n, a, m, k)
if ret[0]:
primes += 1
else:
composites += 1
f.write("n=" + str(n) + ", Primes=" + str(primes) + ", Composites=" + str(composites) + ", Error=" + str(1.0 * primes / (primes + composites)))
f.write("\n")
f.close()
end = time.clock()
t = end - start
print str(t) + " seconds"
#Sorts and then displays errors for the dataset
def stats():
f = open("stats.txt", "r")
data = []
for line in f:
n = int(line.split(",")[0].split("=")[1])
p = int(line.split(",")[1].split("=")[1])
c = int(line.split(",")[2].split("=")[1])
e = float(line.split(",")[3].split("=")[1])
data.append((n, p, c, e))
data.sort(key=lambda x: x[3])
for e in data:
print e
#Command input
while True:
cmd = raw_input("Enter command: ")
if cmd == "it's miller time":
miller_time()
elif cmd == "stats":
stats()
elif cmd == "exit" or cmd == "quit":
break
Vigenère Cipher
This python program can be used to do some analysis on a Vigenère cipher and then try to decrypt it with a given key
Usage:
#:> python vigenere.py Enter command: ioc 4 0.0663865546218 0.0719887955182 0.072268907563 0.06918767507 AVERAGE: 0.0699579831933 Enter command: split 4 hgofttubjastbsfsnzaauftfvaabvvacavygluegzflfeyfbonyjvgflavnzghpgyhhzsvfnpauftxnfaaata dvowchcioqpvicrwqdokpowcgocrbbrdrrwvcwocoohipwofcgzbgogmbgrccgctcqgowbfbazhhamrrourqh smwemsalflvxrpmrlmqmsrvjsqjseklcmyxeywalwjsksxwcyqxmrkmesmvrreyyjlxvpwsxsmgmywsspamsv fkaefkqgmgaqycvvsgslqvdzoskelssansqllvfaadssoalslsglgghjjlqggufdkugqdseagysfjzoogafmq Enter command: key noes uponthisbasisiamgoingtoshowyouhowabunchofbrightyoungfolksdidfindachampionamanwit hboysandgirlsofhisownamanofsodominatingandhappyindividualitythatyouthisdrawntohi masisaflytoasugarbowlitisastoryaboutasmalltownitisnotagossipyyarnnorisitadrymono tonousaccountfullofsuchcustomaryfillinsasromanticmoonlightcastingmurkyshadowsdow nalongwindingcountryroad
'''
vigenere.py
Andrew Burgess (andrew@deceptacle.com)
Corey Greenhawk
Can be used to do some analysis on a ciphertext encoded with a Vigenere cipher and attempt to decrypt
The function "cheat" is used because the ciphertext was said to be from "Gadsby" by Ernest Vincent Wright
Due to this information, it can be found that the plaintext would not contain the letter 'e'
"cheat" takes advantage of this by removing potential key letters that would result in 'e' as the
decrypted plaintext
"cheat_brute" does some further trimming by removing decrypted plaintexts that contain way too many 'x's
or 'z's (guessed amount, but seemed reasonable). This leaves a file with a much smaller possible set
of potential plaintexts which can be quickly scanned to find the key
'''
'''
Guessed keylength of 4 based on results from Index of Coincidence calculations
'''
#Block length of at most 6
cipher = "hdsfgvmkoowafweetcmfthskucaqbilgjofmaqlgspvatvxqbiryscpcfrmvswrvnqlszdmgaoqsakmlupsqforvtwvdfcjzvgsoaoqsacjkbrsevbelvbksarlscdcaarmnvrysywxqgvellcyluwwveoafgclazowafojdlhssfiksepsoywxafowlbfcsocylngqsyzxgjbmlvgrggokgfgmhlmejabsjvgmlnrvqzcrggcrghgeupcyfgtydycjkhqluhgxgzovqswpdvbwsffsenbxapasgazmyuhgsfhmftayjxmwznrsofrsoaopgauaaarmftqsmahvqecev"
#cipher = "lxfopvefrnhr" #Decryptes to "attackatdawn" Key is "lemonlemonle"
base = {} #Used for the base alphabet
for x in range(0, 26):
base[chr(97 + x)] = 0
def split_string(length, s):
substrings = []
p = 0 #Passes
for x in range(1, length + 1):
substrings.append("")
i = 0 + p
while i 4:
return
if "z" in cnt: #drop out way too many z's in the text
if cnt["z"] > 8:
return
f.write("KEY: " + key)
f.write("\n")
f.write(decrypt(key))
f.write("\n\n")
while True:
''' Commands:
ioc Calculates index of coincidence for the keylength
key Attempts to decrypt using the given key
split Splits the ciphertext into the substrings used in IOC
cheat Basically brute forces an answer using the provided keylength
'''
command = raw_input("Enter command: ")
if (command.split(" ")[0] == "ioc"):
ioc(int(command.split(" ")[1]))
elif (command.split(" ")[0] == "key"):
print decrypt(command.split(" ")[1])
elif (command.split(" ")[0] == "split"):
s = split_string(int(command.split(" ")[1]), cipher)
for x in s:
print x
elif (command.split(" ")[0] == "cheat"):
cheat(int(command.split(" ")[1]))
elif (command == "exit"):
break;
Affine Cipher Decryptor
Solves a cipher text encrypted with the Affine cipher using two guessed cipher/plaintext pairs Usage:
#:> python affine.py Trying with two characters... First character (CIPHER=plain): I=a Second character (CIPHER=plain): H=f Guess is: a = 5, b = 8 affinecipher
'''
Affine Cipher Decryptor
Andrew Burgess (andrew@deceptacle.com)
Using two guessed cipher/plaintext character pairs, guesses a key and shows the decrypted text
'''
cipher = "IHHWVCSWFRCP" #Cipher text to crack (becomes affinecipher when solved)
'''
Extended Euclidean Algorithm implementation.
First number returned is the multiplicative inverse for u if v is the base
Third number determines whether u and v are actually coprime. Should be 1 if they are
'''
def eea(u, v):
u1 = 1
u2 = 0
u3 = u
v1 = 0
v2 = 1
v3 = v
while v3 != 0:
q = u3 / v3
t1 = u1 - q * v1
t2 = u2 - q * v2
t3 = u3 - q * v3
u1 = v1
u2 = v2
u3 = v3
v1 = t1
v2 = t2
v3 = t3
return u1, u2, u3
'''
Decrypts a character based on the alpha/beta values of the algorithm
'''
def decrypt(key, shift, char):
v = eea(key, 26)
return chr(((v[0]) * ((ord(char) - 65) - shift) % 26) + 97)
'''
Guesses a key/shift pair based on a CIPHER=plaintext combo
Input Example:
First character: Y=e
Second character: N=j
Returns a pair of integers. The first is the key, and the second is the shift
'''
def guess_key(key1, key2):
p = ord(key1.split("=")[1]) - 97
r = ord(key1.split("=")[0]) - 65
q = ord(key2.split("=")[1]) - 97
s = ord(key2.split("=")[0]) - 65
d = (p - q) % 26
dinv = eea(d, 26)[0]
a = (dinv * (r - s)) % 26
b = (dinv * (p * s - q * r)) % 26
return a, b
'''
Loop to allow multiple guesses without needing to restart the program
'''
while True:
print "Trying with two characters..."
print
key1 = raw_input("First character (CIPHER=plain): ")
key2 = raw_input("Second character (CIPHER=plain): ")
a, b = guess_key(key1, key2)
print "Guess is: a = " + str(a) + ", b = " + str(b)
message = ""
for c in cipher:
message = message + decrypt(a, b, c)
print message
raw_input()
jQuery Masked Input
Found this plugin for jQuery for masking input boxes to restrict input to a specific format. http://digitalbush.com/projects/masked-input-plugin/ Definitely pleased with this plugin. Very easy to use, and the format for specifying masks is easy as well.
$("#CellPhone").mask("(999) 999-9999");
That’s how easy it is to set up a mask. I do have one problem with it though. It’s basically a one to one mapping for characters (you can specify optional sections on the end) but it doesn’t allow something more regex based. For instance: at least one but up to three letters, followed by 6 numbers (a135923 and ab473922). I will probably try to extend it if I ever run across this situation though. Give it a look if you need to restrict input on textboxes.
Creating a Vertically Oriented Table
For the project that I’m working on at my company, one of the pages required developing a table that was vertically oriented (first cell in each row is a header, each data item takes a column). It also had to be editable in place, which means that using a traditional table would be extremely difficult and hackish. I settled on using unordered lists and some jQuery to give the appearance of a table, and it seems to have worked out splendidly.
CSS Styles
.table-container {
border: 1px solid #AAAAAA;
}
.vertical-list-container {
overflow-x:scroll;
width: 600px;
border-left: 1px solid #AAAAAA;
}
.vertical-list {
float: left;
width: 230px;
padding-bottom:10px;
}
.vertical-list .label {
padding-right: 14px;
text-align:left !important;
font-weight: bold;
}
.vertical-list li {
vertical-align: middle;
text-align: center;
margin-top: 5px;
padding: 5px 10px;
min-height: 15px;
border-bottom: 1px dotted #E0E0E0;
border-right: 1px dotted #E0E0E0;
}
jQuery magic to make it more table-y. This code basically extends the inner section (id = “scroller”) to the maximum width of the table columns (based on how many there are). It then stretches the container to fit within the whole parent container that the scroll bar will go all the way across. Finally, it loops through each column, and then uses a custom selector to find any cell heights that are above the minimum amount, and then updates all of the heights for those rows
jQuery
$.extend($.expr[':'], {
height: function (a, i, m) {
//Check to make sure it's :height(>##) or :height(<##)
if (!m[3] || !(/^()\d+$/).test(m[3])) { return false; }
return m[3].substr(0, 1) === ">" ?
$(a).height() > m[3].substr(1) : $(a).height() 15)").each(function (index) {
var z = $(this).index();
var height = $(this).height();
$(".vertical-list").each(function (y) {
$(this).find("li:eq(" + z + ")").height(height);
});
});
});
});
Then finally, here’s the structure for the HTML code that displays the data
HTML
<div class="table-container"> <ul class="vertical-list float-left"> <li>Row Header</li> <li>Row Header</li> </ul> <div class="vertical-list-container"> <div id="scroller"> <ul class="vertical-list"> <li>Item 1, Field 1</li> <li>Item 1, Field 2</li> </ul> <ul class="vertical-list"> <li>Item 2, Field 1</li> <li>Item 2, Field 2</li> </ul> </div> </div> </div>
BP Spills Coffee
Jay shared this, and I thought it was amazing. Check it out