Personal tools

Difference between revisions of "Ruby examples"

From MohidWiki

Jump to: navigation, search
 
(18 intermediate revisions by the same user not shown)
Line 1: Line 1:
==Class IsTheRootStringToTransform==
+
==Jabber bot==
 +
<htm>
 +
<pre name="code" class="ruby">
 +
require 'xmpp4r/client'
  
 +
class JabberBot < Jabber::Client
 +
  include Jabber
 +
 
 +
  def initialize(jabber_id, jabber_password, options = {})
 +
    @jabber_id = jabber_id
 +
    @jabber_password = jabber_password
 +
    @options = options
 +
    @jid = JID::new(@jabber_id)
 +
    # super calls the base_method
 +
    super(@jid)
 +
  end
 +
 
 +
  def on_message(from, body)
 +
    raise "on_message not implemented!"
 +
  end
 +
 
 +
  def connect_and_authenticate
 +
    connect
 +
    auth(@jabber_password)
 +
    send(Presence::new)
 +
    puts "Connected! Send messages to #{@jid.strip.to_s}."
 +
  end
 +
 
 +
  def run
 +
    main = Thread.current
 +
    add_message_callback { |message|
 +
      next if message.type == :error or message.body.blank?
 +
      # support exit command if owner is set
 +
      main.wakeup if @options[:owner_jabber_id] == message.from && message.body == 'exit'
 +
      # simple callback
 +
      self.on_message(message.from, message.body)
 +
    }
 +
    Thread.stop
 +
    close
 +
  end
 +
 
 +
  def say(jabber_id, body)
 +
    send(Message::new(jabber_id, body).set_type(:chat).set_id('1'))
 +
  end
 +
 
 +
end
 +
</pre>
 +
</htm>
 +
==Codebits rfid bot==
 
<htm>
 
<htm>
 
<pre name="code" class="ruby">
 
<pre name="code" class="ruby">
class IsTheRootStringToTransform
+
#!/usr/bin/env ruby
 +
require 'jabber/bot'
 +
require 'socket'
 +
require 'date'
 +
 
 +
def sendreceive(request,ip='85.247.250.5',port=13568)
 +
    puts "initializing socket..."
 +
    TCPSocket.open(ip, port.to_i) do |sock|
 +
        puts "done\n"
 +
        puts "sending request..."
 +
        sock.write(request)
 +
        puts "done\n"
 +
        puts "getting answer..."
 +
        result = sock.read(100)
 +
        puts "done\n"
 +
        sock.close
 +
        return result
 +
    end
 +
end
 +
 
 +
def timefromnow(string)
 +
    now = DateTime.now
 +
    date = DateTime.parse(string)
 +
    days = (now-date).to_f
 +
    secs = days * 86400
 +
    if secs < 60
 +
        msg = secs.to_i + " seconds ago."
 +
    else
 +
        if secs > 59 && secs < 120
 +
            msg = "1 minute ago."
 +
        else
 +
            mins = secs / 60
 +
            if mins < 60
 +
                msg = mins.to_i.to_s + " minutes ago."
 +
            else
 +
                if mins > 59 && mins < 120
 +
                    msg = "1 hour ago."
 +
                else
 +
                    hours = mins / 60
 +
                    if hours < 24
 +
                        msg = hours.to_i.to_s + " hours ago."
 +
                    else
 +
                        if hours > 23 && hours < 48
 +
                            msg = "1 day ago."
 +
                        else
 +
                            days = hours / 24
 +
                            msg = days.to_i.to_s + " days ago."
 +
                        end
 +
                    end
 +
                end
 +
            end
 +
        end
 +
    end
 +
 
 +
    return msg
 +
 
 +
end
 +
 
 +
class Rfidcodebits
 +
 
 +
    def initialize(file = "rfidbits.txt")
 +
        @cache = file
 +
        @results = Array.new
 +
    end
 +
 
 +
    def whereis(message)
 +
 
 +
        flag = false
 +
        File.open(@cache,'r') { |fs|
 +
            pat=message.gsub(/ /,' .*')
 +
            while line = fs.gets
 +
                words = line.split(/\|/)
 +
                if words[5].match(/#{pat}/i) || words[2].match(/^#{message.strip}$/)
 +
                    flag = true
 +
                    @results.push("#{words[5]} (#{words[2]}) was last seen at " + words[1] + ", " + timefromnow(words[3]))
 +
                end
 +
            end
 +
            fs.close
 +
            if !flag
 +
                @results.push("#{message} wasn't found.")
 +
            end
 +
            @results
 +
        }
 +
 
 +
    end
 +
 
 +
end
 +
 
 +
# Create a public Jabber::Bot
 +
bot = Jabber::Bot.new(
 +
  :jabber_id => 'codebits@jabber.cc',
 +
  :password => 'hackathon',
 +
  :master    => 'guillaume.riflet@gmail.com',
 +
  :is_public => true
 +
)
 +
 
 +
# Give your bot a public command
 +
bot.add_command(
 +
  :syntax      => 'rand',
 +
  :description => 'Produce a random number from 0 to 10',
 +
  :regex      => /^rand$/,
 +
  :is_public  => false
 +
) { rand(10).to_s }
 +
 
 +
# Give your bot a private command with an alias
 +
bot.add_command(
 +
  :syntax      => 'puts <string>',
 +
  :description => 'Write something to $stdout',
 +
  :regex      => /^puts\s+.+$/,
 +
  :alias      => [
 +
      :syntax => 'p <string>',
 +
      :regex => /^p\s+.+$/
 +
  ]
 +
) do |sender, message|
 +
  puts message
 +
  "'#{message}' written to $stdout"
 +
end
 +
 
 +
bot.add_command(
 +
    :syntax        => 'whereis <name or id>',
 +
    :description    => 'People spotter, give name or id',
 +
    :regex          => /^whereis */i,
 +
    :alias          => [
 +
        :syntax => 'W',
 +
        :regex  => /^W */i
 +
    ],
 +
    :is_public      => true
 +
) do |sender, message|
 +
    #sendreceive("whereis:#{message}")
 +
    bits = Rfidcodebits.new
 +
    bits.whereis(message).join("\n\n")
 +
end
 +
 
 +
bot.add_command(
 +
  :syntax      => 'kill',
 +
  :description => 'Disconnect me, master.',
 +
  :regex      => /^kill$/,
 +
  :alias      => [
 +
    :syntax => 'K',
 +
    :regex => /^K$/
 +
  ]
 +
) {
 +
  "Ah, you killed me master."
 +
  self.disconnect
 +
}
 +
 
 +
# Bring your new bot to life
 +
begin
 +
  bot.connect
 +
rescue
 +
  puts "The bot got, somehow, disconnected."
 +
end
 +
 
 +
#puts sendreceive("Guillaume\n", 'localhost', 3000)
 +
#puts sendreceive("Guillaume")
 +
 
 +
#mybits = Rfidcodebits.new
 +
#puts mybits.whereis(" 32 ").join("\n")
 +
#puts timefromnow('2008-11-14 17:18:46')
 +
 
 +
</pre>
 +
</htm>
 +
 
 +
==PatternTransform==
 +
 
 +
In this example, we'll see how to use a couple of classes in a ruby program in order to execute in a batch a series of actions to perform with the MOHID utility tools, such as [[ConvertToHdf5]] or [[Hdf5Extractor]].
 +
 
 +
Concretely speaking, the example takes a template file with the configuration of the MOHID utility (such as ''ConvertToHdf5Action.dat'' or ''Hdf5Extractor.dat'') and file with a list of substitutions to perform on the template configuration file, one line per configuration file.
 +
 
 +
===Template file===
 +
Here is an example of the template file:
 +
#root_Hydro_HDF5Extractor.dat
 +
OUTPUTFILENAME          : MOHID_HYDRO_XX.hdf5
 +
 +
FILENAME                : ../Glue/MOHID_HYDRO_XX.hdf5
 +
 +
START_TIME              : 2004 MM SDD 0 0 0
 +
END_TIME                : 2004 MM EDD 0 0 0
 +
 +
CONVERT_V3_TO_V4        : 0
 +
 +
<BeginParameter>
 +
PROPERTY                : velocity U
 +
HDF_GROUP                : /Results/velocity U
 +
<EndParameter>
 +
 +
<BeginParameter>
 +
PROPERTY                : velocity V
 +
HDF_GROUP                : /Results/velocity V
 +
<EndParameter>
 +
 +
<BeginParameter>
 +
PROPERTY                : water level
 +
HDF_GROUP                : /Results/water level
 +
<EndParameter>
 +
 
 +
===Substitutions list===
 +
Here is the file containing the list of substitutions to perform on the above template:
 +
#List.txt
 +
(XX) (MM) (EDD) (SDD)
 +
01    1    31  2
 +
02    2    29  1
 +
03    3    31  1
 +
04    4    30  1
 +
05    5    31  1
 +
06    6    30  1
 +
07    7    31  1
 +
08    8    31  1
 +
09    9    30  1
 +
10    10    31  1
 +
11    11    30  1
 +
12    12    31  1
 +
 
 +
The first line contains the list of strings to match in the template file (such as ''XX'' or ''MM''). Each string to match is between parentheses. The strings to match are space-separated.
 +
The following lines containg the strings to substitute, space-separated. Each new line will correspond to a new configuration file.
 +
 
 +
For example, the substitution of '' (XX) (MM) (EDD) (SDD)'' with '' 01    1    31  2'' on the template file will yield the following result file:
 +
#Hydro_HDF5Extractor_001.dat
 +
OUTPUTFILENAME          : MOHID_HYDRO_01.hdf5
 +
 +
FILENAME                : ../Glue/MOHID_HYDRO_01.hdf5
 +
 +
START_TIME              : 2004 1 2 0 0 0
 +
END_TIME                : 2004 1 31 0 0 0
 +
 +
CONVERT_V3_TO_V4        : 0
 +
 +
<BeginParameter>
 +
PROPERTY                : velocity U
 +
HDF_GROUP                : /Results/velocity U
 +
<EndParameter>
 +
 +
<BeginParameter>
 +
PROPERTY                : velocity V
 +
HDF_GROUP                : /Results/velocity V
 +
<EndParameter>
 +
 +
<BeginParameter>
 +
PROPERTY                : water level
 +
HDF_GROUP                : /Results/water level
 +
<EndParameter>
 +
 
 +
===Program file===
 +
Here is the program code that will generate the suite of configuration files and run the batch of
 +
transformations with ''HDF5Extract'':
 +
 
 +
<htm>
 +
<pre name="code" class="ruby">
 +
require "patterntransform"
 +
 
 +
hextract = IsTheActionToPerformWithFiles.new("root_Hydro_HDF5Extractor.dat", "list.txt")
 +
hextract.transformsInto("Hydro_HDF5Extractor")
 +
hextract.usesAGenericMohidtoolBatchfile("HydroExtract.bat", "HDF5Extractor.exe", "HDF5Extractor.dat")
 +
hextract.ing
 +
 
 +
wextract = IsTheActionToPerformWithFiles.new("root_Water_HDF5Extractor.dat", "list.txt")
 +
wextract.transformsInto("Water_HDF5Extractor")
 +
wextract.usesAGenericMohidtoolBatchfile("WaterExtract.bat", "HDF5Extractor.exe", "HDF5Extractor.dat")
 +
wextract.ing
 +
</pre>
 +
</htm>
 +
 
 +
===Class IsTheActionToPerformWith===
 +
 
 +
<htm>
 +
<pre name="code" class="ruby">
 +
 
 +
class IsTheActionToPerformWith
 
    
 
    
   attr_reader :rootfilecontent, :list, :matches
+
   attr_reader :patterncontent, :listofsubs
   attr_reader :matchexpr, :j, :outfilename, :batch
+
   attr_reader :matchline, :batch
 
    
 
    
   def initialize (rootstring, list)
+
   def initialize (patterncontent, listofsubs)
     @rootfilecontent, @list = rootstring, list
+
     @patterncontent, @listofsubs = patterncontent, listofsubs
     @list = @list.to_a if !@list.is_a?(Array)
+
     @listofsubs = @listofsubs.to_a if !@listofsubs.is_a?(Array)
     @matchexpr = @list.shift
+
     @matchline = @listofsubs.shift
     @matches = @matchexpr.tr('()','').split(' ')
+
     @matches = @matchline.tr('()','').split(' ')
     @closings = @matchexpr.gsub(/\(.+?\)/, '*').split(/\*| /)
+
     @closings = @matchline.gsub(/\(.+?\)/, '*').split(/\*| /)
 
     puts @closings.join(' ')
 
     puts @closings.join(' ')
 
   end
 
   end
 
    
 
    
   def isTransformedByTheBlock
+
  #private
 +
   def thePatternIsTransformedByTheBlock
 
     @j = 1
 
     @j = 1
     @list.each do |line|
+
     @listofsubs.each do |line|
 
       yield line
 
       yield line
 
       @j = @j + 1
 
       @j = @j + 1
Line 25: Line 340:
 
   end
 
   end
 
    
 
    
 +
  #private
 
   def buildHashOfSubs(array)
 
   def buildHashOfSubs(array)
 
     hash = Hash.new
 
     hash = Hash.new
Line 31: Line 347:
 
   end
 
   end
 
    
 
    
   def isTransformedIntoFile(filename)
+
   def transformsInto(filename)
 
      
 
      
 
     @outfilename = filename
 
     @outfilename = filename
     isTransformedByTheBlock{ |line|     
+
     thePatternIsTransformedByTheBlock{ |line|     
       filecontent = String.new( @rootfilecontent )
+
       filecontent = String.new( @patterncontent )
 +
 
 +
      tokens = line.split( ' ' )
 +
      subhash = buildHashOfSubs(tokens)
 +
     
 +
      @matches.each { |element|
 +
        iselement = false
 +
        subhash.each{ |match,sub|
 +
            if (match.eql? element)
 +
                iselement = true
 +
            end
 +
        }
 +
        if !iselement
 +
            filecontent = String.new( filecontent.reject{|n| n.match(element)}.to_s )
 +
        end
 +
      }
 +
      subhash.each { |match, sub| filecontent.replace filecontent.gsub(match, sub) }
 
        
 
        
 
       tokens = line.split( ' ' )
 
       tokens = line.split( ' ' )
Line 41: Line 373:
 
       subhash.each { |match, sub| filecontent.replace filecontent.gsub(match, sub) }
 
       subhash.each { |match, sub| filecontent.replace filecontent.gsub(match, sub) }
 
        
 
        
       mytrgfile = File.new(filename + "_" + @j.to_s.rjust(3,"0") + ".dat", "w")
+
       mytrgfile = File.new(filename + "_" + @j.to_s.rjust(3,"0") + ".dat", "w")
 
       mytrgfile.puts filecontent
 
       mytrgfile.puts filecontent
 
       mytrgfile.close
 
       mytrgfile.close
Line 49: Line 381:
 
      
 
      
 
   end
 
   end
 +
 
    
 
    
   def hasTheFollowingBatchFileBlock(batchfilename)
+
  #Running
 +
   def ing
 +
    puts "Running #{@batchfilename}..."
 +
  end
 +
 
 +
  #Running
 +
  def ning
 +
    ing
 +
  end
 +
 
 +
#Method 1
 +
  def usesTheFollowingBatchfileNameAndBlock(batchfilename)
 +
   
 +
    @batchfilename = batchfilename
 
      
 
      
 
     @batch = String.new
 
     @batch = String.new
 
      
 
      
batchhead = <<HEAD
+
    batchhead = &lt;&lt;HEAD
@echo off
+
    @echo off
for %%i in (#{@outfilename}_*.dat) do (
+
    for %%i in (#{@outfilename}_*.dat) do (
 
HEAD
 
HEAD
  
 
     yield
 
     yield
 
      
 
      
batchfoot = <<FOOT
+
    batchfoot = &lt;&lt;FOOT
)
+
    )
@echo on
+
    pause
 +
    @echo on
 
FOOT
 
FOOT
  
     batchfile = File.new(batchfilename, "w")
+
     batchfile = File.new(@batchfilename, "w")
 
     batchfile.puts batchhead + @batch + batchfoot
 
     batchfile.puts batchhead + @batch + batchfoot
 
     batchfile.close
 
     batchfile.close
Line 72: Line 419:
 
   end
 
   end
  
 +
  #Method 2
 +
  def usesAGenericMohidtoolBatchfile(mohidtool, batchfilename, configfilename)
 +
    usesTheFollowingBatchfileNameAndBlock(batchfilename){
 +
      @batch = &lt;&lt;BATCH
 +
      copy %%i #{configfilename}
 +
      #{mohidtool}
 +
BATCH
 +
    }
 +
  end
 +
 
 +
  def usesAGenericMohidtool(mohidtool, configfilename)
 +
    usesAGenericMohidtoolBatchfile(mohidtool, "All_UseTool.bat", configfilename)
 +
  end
 +
 +
#Methods 3
 +
  def usesAConverttohdf5BatchfileNamed(batchfilename)
 +
    usesAGenericMohidtoolBatchfile( "ConvertToHdf5.exe", batchfilename, "ConvertToHDF5Action.dat")
 +
  end
 +
 
 +
  def usesAConvert2netcdfBatchfileNamed(batchfilename)
 +
    usesAGenericMohidtoolBatchfile( "Convert2Netcdf.exe", batchfilename, "Convert2Netcdf.dat")
 +
  end
 +
 +
end
 +
 +
class IsTheActionToPerformWithFiles &lt; IsTheActionToPerformWith
 +
 
 +
  def initialize(patternfilename, listofsubsfilename)
 +
   
 +
    if File.exists?(patternfilename) and File.exists?(listofsubsfilename) then
 +
     
 +
      #patternfile = File.open(patternfilename)
 +
      patterncontent = String.new( File.open(patternfilename).read )
 +
     
 +
      #listofsubsfile = File.open(listofsubsfilename)
 +
      listofsubs = String.new( File.open(listofsubsfilename).read )
 +
     
 +
      super(patterncontent, listofsubs)
 +
     
 +
    else
 +
     
 +
      puts "Error: one or both of #{patternfilename} or #{listofsubsfilename} doesn't exist."
 +
     
 +
    end
 +
   
 +
  end
 +
 
 +
end
 +
 +
if __FILE__ == $0
 +
 
 +
mycontent = &lt;&lt;CONVERTTOHDF5ACTION
 +
&lt;begin_file&gt;
 +
ACTION                  : GLUES HDF5 FILES
 +
 +
OUTPUTFILENAME          : MOHID_WATER_01.hdf5
 +
 +
&lt;&lt;begin_listofsubs&gt;&gt;
 +
..\\Extraction\\Stride_WaterProperties_1.hdf5
 +
..\\Extraction\\Stride_WaterProperties_2.hdf5
 +
&lt;&lt;end_listofsubs&gt;&gt;
 +
&lt;end_file&gt;
 +
CONVERTTOHDF5ACTION
 +
 +
mylistofsubs = &lt;&lt;listofsubs
 +
_(01) s_(1). s_(2). (WATER) (WaterProperties)
 +
  01      1        2    WATER  WaterProperties
 +
  01      1        2    HYDRO  Hydrodynamic
 +
  02      3        5    WATER  WaterProperties
 +
  02      3        5    HYDRO  Hydrodynamic
 +
listofsubs
 +
 +
  ## 1 Create ##########
 +
  #You can create the class object with files ...
 +
  glue = IsTheActionToPerformWithFiles.new("root_ConvertToHDF5Action.dat", "listofsubs.txt") 
 +
  #... or with strings
 +
  glue = IsTheActionToPerformWith.new(mycontent, mylistofsubs) 
 +
 +
  ## 2 Generate new files ##########
 +
  glue.transformsInto("GlueAction")
 +
 
 +
  ## 3 Generate runscript ##########
 +
  #You can easily customize the batchfile main loop ...
 +
  glue.usesTheFollowingBatchfileNameAndBlock("GlueAllHdf5.bat") {
 +
    glue.batch.replace &lt;&lt;BATCH
 +
      copy %%i ConvertToHdf5Action.dat
 +
      ConvertToHdf5.exe
 +
BATCH
 +
  } 
 +
  #... or use a standard one
 +
  glue.usesAConverttohdf5BatchfileNamed("GlueAllHdf5.bat")
 +
 
 +
  ## 4 Run ##########
 +
  glue.ing
 +
 
 
end
 
end
 +
 
</pre>
 
</pre>
 
</htm>
 
</htm>

Latest revision as of 17:13, 28 October 2010

Jabber bot

require 'xmpp4r/client'

class JabberBot < Jabber::Client
  include Jabber
  
  def initialize(jabber_id, jabber_password, options = {})
    @jabber_id = jabber_id
    @jabber_password = jabber_password
    @options = options
    @jid = JID::new(@jabber_id)
    # super calls the base_method
    super(@jid)
  end
  
  def on_message(from, body)
    raise "on_message not implemented!"
  end
  
  def connect_and_authenticate
    connect
    auth(@jabber_password)
    send(Presence::new)
    puts "Connected! Send messages to #{@jid.strip.to_s}."
  end
  
  def run
    main = Thread.current
    add_message_callback { |message|
      next if message.type == :error or message.body.blank?
      # support exit command if owner is set
      main.wakeup if @options[:owner_jabber_id] == message.from && message.body == 'exit'
      # simple callback
      self.on_message(message.from, message.body)
    }
    Thread.stop
    close
  end
  
  def say(jabber_id, body)
    send(Message::new(jabber_id, body).set_type(:chat).set_id('1'))
  end
  
end

Codebits rfid bot

#!/usr/bin/env ruby
require 'jabber/bot'
require 'socket'
require 'date'

def sendreceive(request,ip='85.247.250.5',port=13568)
    puts "initializing socket..."
    TCPSocket.open(ip, port.to_i) do |sock|
        puts "done\n"
        puts "sending request..."
        sock.write(request)
        puts "done\n"
        puts "getting answer..."
        result = sock.read(100)
        puts "done\n"
        sock.close
        return result
    end
end

def timefromnow(string)
    now = DateTime.now
    date = DateTime.parse(string)
    days = (now-date).to_f
    secs = days * 86400
    if secs < 60
        msg = secs.to_i + " seconds ago."
    else
        if secs > 59 && secs < 120
            msg = "1 minute ago."
        else
            mins = secs / 60
            if mins < 60
                msg = mins.to_i.to_s + " minutes ago."
            else
                if mins > 59 && mins < 120
                    msg = "1 hour ago."
                else
                    hours = mins / 60
                    if hours < 24
                        msg = hours.to_i.to_s + " hours ago."
                    else
                        if hours > 23 && hours < 48
                            msg = "1 day ago."
                        else
                            days = hours / 24
                            msg = days.to_i.to_s + " days ago."
                        end
                    end
                end
            end
        end
    end

    return msg

end

class Rfidcodebits

    def initialize(file = "rfidbits.txt")
        @cache = file
        @results = Array.new
    end

    def whereis(message)

        flag = false
        File.open(@cache,'r') { |fs|
            pat=message.gsub(/ /,' .*')
            while line = fs.gets
                words = line.split(/\|/)
                if words[5].match(/#{pat}/i) || words[2].match(/^#{message.strip}$/)
                    flag = true
                    @results.push("#{words[5]} (#{words[2]}) was last seen at " + words[1] + ", " + timefromnow(words[3]))
                end
            end
            fs.close
            if !flag 
                @results.push("#{message} wasn't found.")
            end
            @results
        }

    end

end

# Create a public Jabber::Bot
bot = Jabber::Bot.new(
  :jabber_id => 'codebits@jabber.cc',
  :password => 'hackathon',
  :master    => 'guillaume.riflet@gmail.com',
  :is_public => true
)

# Give your bot a public command
bot.add_command(
  :syntax      => 'rand',
  :description => 'Produce a random number from 0 to 10',
  :regex       => /^rand$/,
  :is_public   => false
) { rand(10).to_s }

# Give your bot a private command with an alias
bot.add_command(
  :syntax      => 'puts ',
  :description => 'Write something to $stdout',
  :regex       => /^puts\s+.+$/,
  :alias       => [ 
      :syntax => 'p ', 
      :regex => /^p\s+.+$/
  ]
) do |sender, message|
  puts message
  "'#{message}' written to $stdout"
end

bot.add_command(
    :syntax         => 'whereis ',
    :description    => 'People spotter, give name or id',
    :regex          => /^whereis */i,
    :alias          => [
        :syntax => 'W',
        :regex  => /^W */i
    ],
    :is_public      => true
) do |sender, message|
    #sendreceive("whereis:#{message}")
    bits = Rfidcodebits.new 
    bits.whereis(message).join("\n\n")
end

bot.add_command(
   :syntax      => 'kill',
   :description => 'Disconnect me, master.',
   :regex       => /^kill$/,
   :alias       => [
     :syntax => 'K',
     :regex => /^K$/
   ]
) {
  "Ah, you killed me master."
  self.disconnect
}

# Bring your new bot to life
begin
  bot.connect
rescue
  puts "The bot got, somehow, disconnected."
end

#puts sendreceive("Guillaume\n", 'localhost', 3000)
#puts sendreceive("Guillaume")

#mybits = Rfidcodebits.new
#puts mybits.whereis(" 32 ").join("\n")
#puts timefromnow('2008-11-14 17:18:46')


PatternTransform

In this example, we'll see how to use a couple of classes in a ruby program in order to execute in a batch a series of actions to perform with the MOHID utility tools, such as ConvertToHdf5 or Hdf5Extractor.

Concretely speaking, the example takes a template file with the configuration of the MOHID utility (such as ConvertToHdf5Action.dat or Hdf5Extractor.dat) and file with a list of substitutions to perform on the template configuration file, one line per configuration file.

Template file

Here is an example of the template file:

#root_Hydro_HDF5Extractor.dat
OUTPUTFILENAME           : MOHID_HYDRO_XX.hdf5

FILENAME                 : ../Glue/MOHID_HYDRO_XX.hdf5

START_TIME               : 2004 MM SDD 0 0 0
END_TIME                 : 2004 MM EDD 0 0 0

CONVERT_V3_TO_V4         : 0

<BeginParameter>
PROPERTY                 : velocity U
HDF_GROUP                : /Results/velocity U
<EndParameter>

<BeginParameter>
PROPERTY                 : velocity V
HDF_GROUP                : /Results/velocity V
<EndParameter>

<BeginParameter>
PROPERTY                 : water level
HDF_GROUP                : /Results/water level
<EndParameter>

Substitutions list

Here is the file containing the list of substitutions to perform on the above template:

#List.txt
(XX) (MM) (EDD) (SDD)
01    1     31  2
02    2     29  1
03    3     31  1
04    4     30  1
05    5     31  1
06    6     30  1
07    7     31  1
08    8     31  1
09    9     30  1
10    10    31  1
11    11    30  1
12    12    31  1

The first line contains the list of strings to match in the template file (such as XX or MM). Each string to match is between parentheses. The strings to match are space-separated. The following lines containg the strings to substitute, space-separated. Each new line will correspond to a new configuration file.

For example, the substitution of (XX) (MM) (EDD) (SDD) with 01 1 31 2 on the template file will yield the following result file:

#Hydro_HDF5Extractor_001.dat
OUTPUTFILENAME           : MOHID_HYDRO_01.hdf5

FILENAME                 : ../Glue/MOHID_HYDRO_01.hdf5

START_TIME               : 2004 1 2 0 0 0
END_TIME                 : 2004 1 31 0 0 0

CONVERT_V3_TO_V4         : 0

<BeginParameter>
PROPERTY                 : velocity U
HDF_GROUP                : /Results/velocity U
<EndParameter>

<BeginParameter>
PROPERTY                 : velocity V
HDF_GROUP                : /Results/velocity V
<EndParameter>

<BeginParameter>
PROPERTY                 : water level
HDF_GROUP                : /Results/water level
<EndParameter>

Program file

Here is the program code that will generate the suite of configuration files and run the batch of transformations with HDF5Extract:


require "patterntransform"

hextract = IsTheActionToPerformWithFiles.new("root_Hydro_HDF5Extractor.dat", "list.txt")
hextract.transformsInto("Hydro_HDF5Extractor")
hextract.usesAGenericMohidtoolBatchfile("HydroExtract.bat", "HDF5Extractor.exe", "HDF5Extractor.dat")
hextract.ing

wextract = IsTheActionToPerformWithFiles.new("root_Water_HDF5Extractor.dat", "list.txt")
wextract.transformsInto("Water_HDF5Extractor")
wextract.usesAGenericMohidtoolBatchfile("WaterExtract.bat", "HDF5Extractor.exe", "HDF5Extractor.dat")
wextract.ing


Class IsTheActionToPerformWith


class IsTheActionToPerformWith
  
  attr_reader :patterncontent, :listofsubs
  attr_reader :matchline, :batch
  
  def initialize (patterncontent, listofsubs)
    @patterncontent, @listofsubs = patterncontent, listofsubs
    @listofsubs = @listofsubs.to_a if !@listofsubs.is_a?(Array)
    @matchline = @listofsubs.shift
    @matches = @matchline.tr('()','').split(' ')
    @closings = @matchline.gsub(/\(.+?\)/, '*').split(/\*| /)
    puts @closings.join(' ')
  end
  
  #private
  def thePatternIsTransformedByTheBlock
    @j = 1
    @listofsubs.each do |line|
      yield line
      @j = @j + 1
    end
  end
  
  #private
  def buildHashOfSubs(array)
    hash = Hash.new
    array.size.times { |i| hash.store(@matches[i], @closings[2*i].chomp + array[i] + @closings[2*i + 1].chomp) }
    return hash
  end
  
  def transformsInto(filename)
    
    @outfilename = filename
    thePatternIsTransformedByTheBlock{ |line|    
      filecontent = String.new( @patterncontent )

      tokens = line.split( ' ' )
      subhash = buildHashOfSubs(tokens)
      
      @matches.each { |element| 
        iselement = false
        subhash.each{ |match,sub| 
            if (match.eql? element) 
                iselement = true
            end
        }
        if !iselement 
            filecontent = String.new( filecontent.reject{|n| n.match(element)}.to_s )
        end
      }
      subhash.each { |match, sub| filecontent.replace filecontent.gsub(match, sub) }
      
      tokens = line.split( ' ' )
      subhash = buildHashOfSubs(tokens)
      subhash.each { |match, sub| filecontent.replace filecontent.gsub(match, sub) }
      
      mytrgfile = File.new(filename + "_" + @j.to_s.rjust(3,"0")  + ".dat", "w")
      mytrgfile.puts filecontent
      mytrgfile.close
      
      puts filecontent
    }
    
  end

  
  #Running
  def ing
    puts "Running #{@batchfilename}..."
  end
  
  #Running
  def ning
    ing
  end

#Method 1
  def usesTheFollowingBatchfileNameAndBlock(batchfilename)
    
    @batchfilename = batchfilename
    
    @batch = String.new
    
    batchhead = <<HEAD
    @echo off
    for %%i in (#{@outfilename}_*.dat) do (
HEAD

    yield
    
    batchfoot = <<FOOT
    )
    pause
    @echo on
FOOT

    batchfile = File.new(@batchfilename, "w")
    batchfile.puts batchhead + @batch + batchfoot
    batchfile.close
    
  end

  #Method 2
  def usesAGenericMohidtoolBatchfile(mohidtool, batchfilename, configfilename)
    usesTheFollowingBatchfileNameAndBlock(batchfilename){
      @batch = <<BATCH
      copy %%i #{configfilename}
      #{mohidtool}
BATCH
    }
  end
  
  def usesAGenericMohidtool(mohidtool, configfilename)
    usesAGenericMohidtoolBatchfile(mohidtool, "All_UseTool.bat", configfilename)
  end

#Methods 3
  def usesAConverttohdf5BatchfileNamed(batchfilename)
    usesAGenericMohidtoolBatchfile( "ConvertToHdf5.exe", batchfilename, "ConvertToHDF5Action.dat")
  end
  
  def usesAConvert2netcdfBatchfileNamed(batchfilename)
    usesAGenericMohidtoolBatchfile( "Convert2Netcdf.exe", batchfilename, "Convert2Netcdf.dat")
  end

end

class IsTheActionToPerformWithFiles < IsTheActionToPerformWith
  
  def initialize(patternfilename, listofsubsfilename)
    
    if File.exists?(patternfilename) and File.exists?(listofsubsfilename) then
      
      #patternfile = File.open(patternfilename)
      patterncontent = String.new( File.open(patternfilename).read )
      
      #listofsubsfile = File.open(listofsubsfilename)
      listofsubs = String.new( File.open(listofsubsfilename).read )
      
      super(patterncontent, listofsubs)
      
    else
      
      puts "Error: one or both of #{patternfilename} or #{listofsubsfilename} doesn't exist."
      
    end
    
  end
  
end

if __FILE__ == $0
  
mycontent = <<CONVERTTOHDF5ACTION
<begin_file>
ACTION                   : GLUES HDF5 FILES

OUTPUTFILENAME           : MOHID_WATER_01.hdf5
 
<<begin_listofsubs>>
..\\Extraction\\Stride_WaterProperties_1.hdf5
..\\Extraction\\Stride_WaterProperties_2.hdf5
<<end_listofsubs>>
<end_file>
CONVERTTOHDF5ACTION

mylistofsubs = <<listofsubs
_(01) s_(1). s_(2). (WATER) (WaterProperties)
   01      1        2    WATER   WaterProperties
   01      1        2    HYDRO   Hydrodynamic
   02      3        5    WATER   WaterProperties
   02      3        5    HYDRO   Hydrodynamic
listofsubs

  ## 1 Create ##########
  #You can create the class object with files ...
  glue = IsTheActionToPerformWithFiles.new("root_ConvertToHDF5Action.dat", "listofsubs.txt")  
  #... or with strings
  glue = IsTheActionToPerformWith.new(mycontent, mylistofsubs)  

  ## 2 Generate new files ##########
  glue.transformsInto("GlueAction")
  
  ## 3 Generate runscript ##########
  #You can easily customize the batchfile main loop ...
  glue.usesTheFollowingBatchfileNameAndBlock("GlueAllHdf5.bat") {
    glue.batch.replace <<BATCH
      copy %%i ConvertToHdf5Action.dat
      ConvertToHdf5.exe
BATCH
  }  
  #... or use a standard one
  glue.usesAConverttohdf5BatchfileNamed("GlueAllHdf5.bat")
  
  ## 4 Run ##########
  glue.ing
  
end