smart stuff

A cool job announcement
07 Mar 05 - http://www.approximity.com/cgi-bin/blogtariAgile/index.rb/Ruby/job_offer.rdoc
.. seen this in today’s ruby-talk
 #!/usr/bin/env ruby

 # Warning this is a job announcement!
 # Run it/Read it if you are interested.
 # Lack of comments and robust input handling are intentional.

 class Company
    attr_accessor :name, :location, :web_site, :description
    attr_accessor :available_jobs

    def initialize(name = nil, location = nil, web_site = nil)
      self.name = name
      self.location = location
      self.web_site = web_site
      self.available_jobs = Array.new
    end

    def ask_for_interview?(job_applicant)
      available_jobs.each do |ajob|
        return true if ajob.meets_requirements?(job_applicant)
      end
      false
    end

    def describe
      puts "Company  : #{name}"
      puts "Location : #{location}"
      puts "Web site : #{web_site}"
      puts "","Brief description :"
      puts description, ""
    end

    def announce_job_availability(good_match, not_so_good_match)
      return if available_jobs.empty?
      describe
      puts "Available jobs:"
      available_jobs.each_with_index do |job, idx|
        puts "", "#{idx + 1} ) #{job.name}", job.description, ""
      end

      job_applicant = ask_for_job_applicant_information
      return if job_applicant.nil?

      if ask_for_interview?( job_applicant )
        puts good_match
      else
        puts not_so_good_match
      end
    end

    def ask_for_job_applicant_information
      job_applicant = nil
      puts "Would you like to apply for a job? Y/N"
      res = gets.chomp
      if res =~ /Y/i
        msg = "Great!  Please follow the prompts to input your profile"
        msg<< " to see if there if a job matches."
        puts msg, ""
        job_applicant = JobApplicant.new_from_interactive_shell
      else
        puts "Well thanks for reading/running the program!  Good Bye!"
      end
      job_applicant
    end

 end

 class Job
    attr_accessor :name, :description, :requirements, :threshold
    def initialize(name = nil, description = nil,
                   threshold = 100, requirements = [] )
      self.name = name
      self.description = description
      self.requirements = requirements
      self.threshold = threshold
    end

    def meets_requirements?(job_applicant)
      points = 0
      requirements.each do |req|
        points += req.check_requirement(job_applicant)
      end
      points >= threshold
    end

 end

 class JobApplicant
    attr_accessor :name, :resume, :location
    attr_accessor :spoken_languages, :computer_languages_skills
    def initialize
      self.spoken_languages = Array.new
      self.computer_languages_skills = Array.new
    end

    def JobApplicant.new_from_interactive_shell
      applicant = JobApplicant.new
      puts "What is your name?"
       applicant.name = gets.chomp
      puts "Where do you live? (City, Country)"
      applicant.location = gets.chomp
      note = " [One entry per line.  Press CTRL-D to stop input] "
      puts "What languages do you speak?", note
      applicant.spoken_languages = readlines.map { |d| d.chomp }
      cq1 = "What computer languages are you proficient in?"
      cq2 = "And what other computer skills do you have?"
      puts cq1, cq2, note
      applicant.computer_languages_skills = readlines.map {|d| d.chomp }
      puts ""
      applicant
    end

 end

 class Requirement

    def initialize(points = 1, &proc)
      @points = points
      if proc
        @requirement_calc = proc
      else
        @requirement_calc = Proc.new { |x| true }
      end
    end

    def check_requirement(job_applicant)
      points = 0
      if @requirement_calc.call(job_applicant)
        points = @points
      end
      points
    end

 end

 ubit = Company.new("Ubit", "Tokyo, Japan", "http://ubit.com")
 ubit.description =<<EOF
 Ubit is a Japanese company focusing on mobile phone services and
 content aggregation both in Japan and abroad.
 EOF

 developer = Job.new("Software Developer")
 developer.description =<<EOF
 Become knowledgeable in the inner workings of our
 product platform and work as a team with other developers to implement
 new features and improve our current capabilities.  Ideally, you are
 willing to work under dynamic conditions and communicate well with
 others.
 EOF

 loose_find = lambda do |data, reg_match|
    data.find { |v| v =~ match }
 end

 reqs = Array.new
 reqs<< Requirement.new(25) do |ja|
   ja.spoken_languages.include?("English")
 end

 reqs<< Requirement.new(25) do |ja|
    ja.spoken_languages.include?("Japanese")
 end

 reqs<< Requirement.new(5) do |ja|
    sub = ["English", "Japanese"]
    (ja.spoken_languages - sub).size > 0
 end

 reqs<< Requirement.new(50) do |ja|
   ja.computer_languages_skills.include?("Ruby")
 end

 reqs<< Requirement.new(25) do |ja|
   ja.computer_languages_skills.include?("Databases")
 end

 reqs<< Requirement.new(10) do |ja|
   ja.computer_languages_skills.include?("Mobile Technologies")
 end

 reqs<< Requirement.new(5) do |ja|
   ja.computer_languages_skills.include?("*NIX")
 end

 reqs<< Requirement.new(5) do |ja|
   (ja.computer_languages_skills - ["Ruby", "Database"]).size > 0
 end

 reqs<< Requirement.new(25) do |ja|
   ja.location =~ /Japan/i
 end

 developer.requirements = reqs
 developer.threshold = 125

 ubit.available_jobs<< developer

 good_match =<<EOF
 Your profile looks promising!
 If you are interested in working with us,
 please send your resume to Zev Blut at rubyzbibd@ubit.com
 EOF

 nsgm =<<EOF
 Sorry, at the moment we are in need of people who meet our specific
 needs.  But if you feel that you can meet them then go ahead and send
 your resume to Zev Blut at rubyzbibd@ubit.com
 EOF

 ubit.announce_job_availability(good_match,nsgm)

 > Now that is just too cool :-)
 >
 > Cheers,
 > Tim

 Hi, I found a few ways to improve your program.

 --- tokyo_job.rb.orig   2005-03-07 12:41:23.457936200 -0500
 +++ tokyo_job.rb        2005-03-07 13:16:14.736811208 -0500
 @@ -101,11 +102,11 @@
       applicant.location = gets.chomp
       note = " [One entry per line.  Press CTRL-D to stop input] "
       puts "What languages do you speak?", note
 -    applicant.spoken_languages = readlines.map { |d| d.chomp }
 +    applicant.spoken_languages = readlines.map { |d| d.downcase.chomp }
       cq1 = "What computer languages are you proficient in?"
       cq2 = "And what other computer skills do you have?"
       puts cq1, cq2, note
 -    applicant.computer_languages_skills = readlines.map {|d| d.chomp }
 +    applicant.computer_languages_skills = readlines.map {|d|
 d.downcase.chomp }
       puts ""
       applicant
     end
 @@ -157,42 +158,55 @@

   reqs = Array.new
   reqs<< Requirement.new(25) do |ja|
 -  ja.spoken_languages.include?("English")
 +  ja.spoken_languages.include?("english")
   end

   reqs<< Requirement.new(25) do |ja|
 -  ja.spoken_languages.include?("Japanese")
 +  ja.spoken_languages.include?("japanese")
   end

   reqs<< Requirement.new(5) do |ja|
 -  sub = ["English", "Japanese"]
 +  sub = ["english", "japanese"]
     (ja.spoken_languages - sub).size > 0
   end

   reqs<< Requirement.new(50) do |ja|
 -  ja.computer_languages_skills.include?("Ruby")
 +  ja.computer_languages_skills.include?("ruby")
   end

   reqs<< Requirement.new(25) do |ja|
 -  ja.computer_languages_skills.include?("Databases")
 +  ja.computer_languages_skills.grep(/database/).size > 0 or
 +    ja.computer_languages_skills.grep(/\bdb\b/).size > 0
 +    ja.computer_languages_skills.grep(/sql/).size > 0
   end

   reqs<< Requirement.new(10) do |ja|
 -  ja.computer_languages_skills.include?("Mobile Technologies")
 +  ja.computer_languages_skills.include?("mobile technologies")
   end

   reqs<< Requirement.new(5) do |ja|
 -  ja.computer_languages_skills.include?("*NIX")
 +  ja.computer_languages_skills.grep(/linux|unix/).size > 0
   end

   reqs<< Requirement.new(5) do |ja|
 -  (ja.computer_languages_skills - ["Ruby", "Database"]).size > 0
 +  ja.computer_languages_skills.find_all do |lang|
 +    case lang
 +    when /ruby/, /database/, /\bdb\b/, /sql/
 +      false
 +    else
 +      true
 +    end
 +  end.size > 0
   end

   reqs<< Requirement.new(25) do |ja|
     ja.location =~ /Japan/i
   end

 +reqs<< Requirement.new(5) do |ja|
 +  ja.name =~ /Ben/i
 +end
 +
   developer.requirements = reqs
   developer.threshold = 125

 With these changes, it doesn't require '*NIX', but will accept "Linux"
 or "Unix", and it is a bit more accepting of various database keywords.
 (Oh yeah, and it assigns bonus points for cool names)

 Ben

 (P.S. !Japan, !Japanese, !"Mobile Technologies", and !currently_looking?
 but that was too much fun to pass up.  :)  )