Tag Archives: Ruby

Old Ruby Script : Rnaarerge ltreets iisnde wdors and sltil raed tehm

This little gem comes from October 20, 2006. I had just heard about the research saying that as long as you keep the first and last letters of a word in place the order of the other letters doesn’t matter. Supposedly your mind will still figure out the correct order. It turns out that this e-mail forward wasn’t as impressive as it made out to be, but the script was fun to make anyways. Here’s what the e-mail said:

Aoccdrnig to a rscheearch at Cmabrigde Uinervtisy, it deosn’t mttaer in waht oredr the ltteers in a wrod are, the olny iprmoetnt tihng is taht the frist and lsat ltteer be at the rghit pclae. The rset can be a toatl mses and you can sitll raed it wouthit porbelm. Tihs is bcuseae the huamn mnid deos not raed ervey lteter by istlef, but the wrod as a wlohe.

I was playing with Ruby at the time, so I put together a short script to make those kinds of sentences. Here’s the code:

#!/usr/bin/env ruby
puts "Enter your phrase to be mixed"
def swap(a,b) ($x[a],$x[b] = $x[b],$x[a]) if (a > 0 && a < $x.length - 2) end
myarray = STDIN.readline.split(' ').each {|$x| $x.split('').each_index { |w| swap(w, rand($x.length - 2) + 1)}}
puts myarray.join(' ')

If you want to try it, save it to as a Ruby file on a computer with Ruby installed, and run it from the command line. It will ask you for a line of text. Each word (or space separated group of characters) will keep its first and last character in place, while the others will be mixed up.

Apparently I used this script to explain Ruby to someone, as I also found an explanation file:

#!/usr/bin/env ruby

# prints the prompt
puts "Enter your phrase to be mixed"

# defines a new subroutine named 'swap(a,b)'. swap takes two parameters
def swap(a,b)
# In ruby, you can add an if after the operations, as I did here. The operation swaps the items at indexes a and b
# The if part makes sure we're not swapping the first or last charachters
($x[a],$x[b] = $x[b],$x[a]) if (a > 0 && a < $x.length - 2)
# End of the subroutine
end

#sets the variable myarray to the results of the operation
#STDIN.readline -- Get one line from stdin (ie. from the terminal)
#.split(' ') -- split the preceding object on each space and put into an array
#.each -- for each element in the array (handle defined here as global variable |$x|) do what follows the variable declaration
#$x.split('') -- split on each letter and put into the array
#.each_index -- similar to each, but instead, the variable (|w|) is the index of each element, one at a time
#swap(w,z) -- call the swap subroutine with parameters of w and z
#rand($x.length -2) + 1) -- gives a random index in the word not including the first or last letter
myarray = STDIN.readline.split(' ').each {|$x| $x.split('').each_index { |w| swap(w, rand($x.length - 2) + 1)}}

#prints each element of the myarray variable with a space in between
puts myarray.join(' ')

So that’s that. Maybe it’ll help with learning Ruby? Or making funny sentences? Or wasting your time?

Posted in Computers, Something Interesting | Tagged | 2 Comments

CSS color extracter

This is one of the reasons I love Ruby. I wrote some code that would take a CSS file and print out the unique hex colors, and it was about 10 lines long. I then realized that if I had been thinking in Ruby, I could do it in just one line.

This page is OLD and probably contains errors, out of date information, security flaws or other problems. I am keeping it around because it might be helpful to someone.

File.readlines(ARGV[0]).to_s.downcase.scan(/#[0-9a-f]{6}/).uniq.sort.each {|one| puts one} if (ARGV[0] != nil)

Put that in a Ruby file, and run it with a parameter of the CSS file to parse, and it will print each unique color on a single line.

Expanding on that work, we can now create Gimp palettes for use in a variety of Open Source graphics programs, including Inkscape and The Gimp. Here is a program that will do just that.
Download it here

#!/usr/bin/env ruby
# Create a gimp palette from a CSS file's unique hex colors
# Weakenesses: Doesn't account for 3 digit colors (ie. #abc;)
# or for named colors
#
# By Michael Moore stuporglue@gmail.com
# Released to Public Domain April 5, 2007
if (ARGV[0] != nil)
    gimpstring = "GIMP Palette\nName: "
    if(ARGV[1] != nil)
	gimpstring << ARGV[1]
    else
	gimpstring << ARGV[0]
    end
    gimpstring << "\nColumns: 0\n#"
    # This could have problems if you have ids that are only hex chars for the first 6 values
    # eg. if this were your CSS
    #
    #	#abc123nurserystyle {
    # 		background-color: green;
    #	}
    #
    #	the color #abc123 would be added to the palette

    File.readlines(ARGV[0]).to_s.downcase.scan(/#[0-9a-f]{6}/).uniq.sort.each do |onecolor|
	colorparts = onecolor.scan(/[0-9a-f]{2}/)
	gimpstring << "\n" + colorparts[0].hex.to_s.rjust(3) + " " + colorparts[1].hex.to_s.rjust(3) + " " + colorparts[2].hex.to_s.rjust(3) + "\tUntitled"
    end
    print gimpstring
else
    puts ""
    puts "CSS to Gimp Palette"
    puts "Use 6-digit hex colors from a CSS file to create a Gimp palette (gpl) file"
    puts ""
    puts "USAGE: csstogpl.rb cssfile [Palette Name]"
    puts "If Palette Name is ommited, the CSS file's name will be used instead"
    puts ""
    puts "Note: csstogpl does not write to a file, it prints to stdout."
    puts "To save to a file, use redirection. eg."
    puts "csstogpl.rb style.css MyAwesomeColorScheme > MACS.gpl"
    puts ""
end
Posted in Programming, Projects | Tagged , , , , | Leave a comment

Ruby Chat/Web Server

For another class I had to write a threaded server that would serve up a chat server on port 9020. The server had to give a new user the last 100 lines of chat in that room, and had to update one user’s page even if they didn’t send anything (ie. so they could see the other people’s chat).

This page is OLD and probably contains errors, out of date information, security flaws or other problems. I am keeping it around because it might be helpful to someone.
This server:

  • Serves up normal web pages on port 9020
    • Searching for index.html if no file is given
  • Has a special CHAT resource (visit servername:9020/CHAT to access it) with a chat room
  • Has five default chat rooms, more can be added by the users
  • Supports smilies
  • Uses Ajax for the updates so it is a seamless user experience

If you’re going to try to run it, you probably want to download the HTML and JavaScript for the chat page

#!/usr/bin/env ruby
# By Michael Moore, Brad Yates, and Sean Moe

require 'webrick' # require needed libraries (included in ruby)
include WEBrick
require 'cgi' # easy parsing of QUERY_STRING

def roomlist(whowantsin)
    retstring = "<ul>"
    $chatrooms.each_key { |key| retstring = retstring + "<li><a href=\"/CHAT?name=#{whowantsin}&room=#{key}\">#{key}</a></li>"}
    retstring = retstring + "</ul>"
    return retstring
end

def newchatroom(roomname)
    $chatrooms[roomname] = Array.new()
    $chatrooms[roomname] << ""
end
# map of ascii string to the png number
$smileys = { ":-)" => 1, ":-(" => 2, ";-)" => 3, ":-D" => 5, ":-x" => 7, ":-o" => 12}

$smileystring = ""
$smileys.each_key {|key| $smileystring = $smileystring + "<img src=\"/AIM/#{$smileys[key]}.png\" onclick=\"put('#{key}');\">"}

def smile(line) # do some substitution here to put in smileys
    $smileys.each_key {|key| line.gsub!(key,"<img src=\"/AIM/#{$smileys[key]}.png\">")}
    line.gsub!("@wesome","<img src=\"/AIM/renshaw.png\">")
    return line
end
$chatrooms = Hash.new()#Hash of chat arrays. Each room gets an array.  

["default", "Cars", "Dogs", "Science", "Linux"].each { |x| newchatroom(x)}#Create these chat rooms by default

$userhash = Hash.new() # One user per name
class User
    def initialize(name)
	@myname = name
	stamp()
	setroom('default') # calls function below to not duplicate functionality
    end

    def stamp() # update user's timestamp
	@last = Time.now
    end

    def tooold() # Tell if still active
	return (Time.now - @last > 1800) # Return true if they've been active in the last 30 mins
    end

    def setroom(newroom) #change the user's room and their index
	if ($chatrooms[newroom] == nil) # Create the chatroom if needed
	    newchatroom(newroom)
	end
	@chatroom = $chatrooms[newroom]
	@roomname = newroom

	@index = @chatroom.length - 100 # give starting point of this user's chat log.
	@index = 0 if @index < 0 #if the chat log isn't big, set the index to 0
    end

    def lines() # return user's chat lines
	return smile(@chatroom[@index..(@chatroom.length - 1)].join)
    end

    def chat(newlines) # Append new chat to whatever room the user is in
	@chatroom << "<b>#{@myname}: </b>#{newlines}<br>"
    end

    def roomname()
	return @roomname
    end
end

$docroot = "/home/bradkarhu/Desktop/Chatlab"  # Set document root as a global variable
server = HTTPServer.new(:Port => 9020,:DocumentRoot => $docroot)  # new HTTP server on localhost:9020

class SuperServlet  < HTTPServlet::AbstractServlet #  Normal HTTP server mode, with index.html as the default file type
    def do_GET(req, res)  # req == HTTP request object, res == HTTP response object
	filename = req.meta_vars["PATH_INFO"].gsub(req.meta_vars["QUERY_STRING"],"") # Get just the requested filename
	if filename[filename.length - 1] == '/' # Requested a folder, with no file
	    filename = req.meta_vars["PATH_INFO"] + "index.html"
	elsif filename.index('.') == nil  # Requested something, probably a folder
	    filename = req.meta_vars["PATH_INFO"] + "/index.html"
	end
	res['content-length'] = File::stat($docroot + filename).size # without this, the browser doesn't know when to quit?
	res.body = open($docroot + filename, "rb") # return the file contents
    end
end
server.mount("/", SuperServlet) # This applet (SuperServlet) will handle everything by default 

class ChatServer < HTTPServlet::AbstractServlet
    def do_GET(req,res)
	res['Content-Type'] = "text/html" # this applet always returns HTML. JPG and other requests go through SuperServlet
	$form_vars = CGI.parse(req.meta_vars["QUERY_STRING"]) # parse QUERY_STRING vars into nice array

	uname = $form_vars['name'].to_s
	line = $form_vars['line'].to_s
	room = $form_vars['room'].to_s
	who = $form_vars['chatlines'].to_s
	roomlist = $form_vars['roomlist'].to_s

	# Return list of chatrooms
	if (roomlist != "" && roomlist != nil)
	    res.body = roomlist(roomlist)
	    return
	end

	if (uname != "" && uname != nil) #Got a user var
	    if($userhash[uname] == nil || $userhash[uname].tooold()) # create user, and assign to room
		$userhash[uname] = User.new(uname)
		res.body = "<html><head><script type='text/javascript'>window.location='/CHAT?name=#{uname}';</script></head></html>"
	    	return
	    end

	    $userhash[uname].stamp() # Always stamp user

	    if(room != "" && room != nil) #change rooms
		$userhash[uname].setroom(room)
	    end

	    if(line != "" && line != nil)
		$userhash[uname].chat(line)
		res.body = "<html><head><script type='text/javascript'>window.location='/CHAT?name=#{uname}';</script></head></html>"
		return
	    end

	    # Set page body content to mainpage.html, with some substitutions
	    slurp = File.readlines('mainpage.html').to_s
	    slurp.gsub!("chattycontent",$userhash[uname].lines())
	    slurp.gsub!("userformline","<input type=\"hidden\" id=\"name\" name=\"name\" value=\"#{uname}\">")
	    slurp.gsub!("roomname",$userhash[uname].roomname())
	    slurp.gsub!("roomlist",roomlist(uname))
	    slurp.gsub!("happyfaces",$smileystring)
	    slurp.gsub!("username","<div id=\"hiddenuser\" style=\"visibility: hidden;\">#{uname}</div>")
	    res.body = slurp 

	elsif (who != "") # just send back the chatlines
	    res.body = $userhash[who].lines()
	else
	    res.body = File.readlines('chatform.html').join
	end
    end
end
server.mount("/CHAT",ChatServer)

trap("INT"){server.shutdown}     # Catch ctrl-c to do a clean shutdown
server.start # Start the server!
Posted in Programming | Tagged , , , | 2 Comments