Personal tools

Difference between revisions of "Ruby examples"

From MohidWiki

Jump to: navigation, search
(Class PatternTransform)
 
(16 intermediate revisions by the same user not shown)
Line 1: Line 1:
==Class IsTheRootStringToTransform==
+
==Jabber bot==
 
 
 
<htm>
 
<htm>
 
<pre name="code" class="ruby">
 
<pre name="code" class="ruby">
class IsTheRootStringToTransform
+
require 'xmpp4r/client'
 +
 
 +
class JabberBot < Jabber::Client
 +
  include Jabber
 
    
 
    
   attr_reader :rootfilecontent, :list, :matches
+
   def initialize(jabber_id, jabber_password, options = {})
   attr_reader :matchexpr, :j, :outfilename, :batch
+
    @jabber_id = jabber_id
 +
    @jabber_password = jabber_password
 +
    @options = options
 +
    @jid = JID::new(@jabber_id)
 +
    # super calls the base_method
 +
    super(@jid)
 +
   end
 
    
 
    
   def initialize (rootstring, list)
+
   def on_message(from, body)
     @rootfilecontent, @list = rootstring, list
+
     raise "on_message not implemented!"
    @list = @list.to_a if !@list.is_a?(Array)
 
    @matchexpr = @list.shift
 
    @matches = @matchexpr.tr('()','').split(' ')
 
    @closings = @matchexpr.gsub(/\(.+?\)/, '*').split(/\*| /)
 
    puts @closings.join(' ')
 
 
   end
 
   end
 
    
 
    
   def isTransformedByTheBlock
+
   def connect_and_authenticate
     @j = 1
+
     connect
     @list.each do |line|
+
     auth(@jabber_password)
      yield line
+
    send(Presence::new)
      @j = @j + 1
+
    puts "Connected! Send messages to #{@jid.strip.to_s}."
    end
 
 
   end
 
   end
 
    
 
    
   def buildHashOfSubs(array)
+
   def run
     hash = Hash.new
+
     main = Thread.current
     array.size.times { |i| hash.store(@matches[i], @closings[2*i].chomp + array[i] + @closings[2*i + 1].chomp) }
+
     add_message_callback { |message|
     return hash
+
      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
 
   end
 
    
 
    
   def isTransformedIntoFile(filename)
+
   def say(jabber_id, body)
      
+
     send(Message::new(jabber_id, body).set_type(:chat).set_id('1'))
    @outfilename = filename
 
    isTransformedByTheBlock{ |line|   
 
      filecontent = String.new( @rootfilecontent )
 
     
 
      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
 
   end
 
    
 
    
  def hasTheFollowingBatchFileBlock(batchfilename)
+
end
      
+
</pre>
     @batch = String.new
+
</htm>
      
+
==Codebits rfid bot==
batchhead = <<HEAD
+
<htm>
@echo off
+
<pre name="code" class="ruby">
for %%i in (#{@outfilename}_*.dat) do (
+
#!/usr/bin/env ruby
HEAD
+
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
  
    yield
+
# Create a public Jabber::Bot
   
+
bot = Jabber::Bot.new(
batchfoot = <<FOOT
+
  :jabber_id => 'codebits@jabber.cc',
 +
  :password => 'hackathon',
 +
  :master    => 'guillaume.riflet@gmail.com',
 +
  :is_public => true
 
)
 
)
@echo on
 
FOOT
 
  
    batchfile = File.new(batchfilename, "w")
+
# Give your bot a public command
     batchfile.puts batchhead + @batch + batchfoot
+
bot.add_command(
     batchfile.close
+
  :syntax      => 'rand',
   
+
  :description => 'Produce a random number from 0 to 10',
   end
+
  :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
 
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>
 
</pre>
 
</htm>
 
</htm>
  
==Class IsTheActionToPerformWith==
+
==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>
 
<htm>
Line 111: Line 347:
 
   end
 
   end
 
    
 
    
   def usesTransformedFilesNamedAfter(filename)
+
   def transformsInto(filename)
   
 
 
      
 
      
 
     @outfilename = filename
 
     @outfilename = filename
 
     thePatternIsTransformedByTheBlock{ |line|     
 
     thePatternIsTransformedByTheBlock{ |line|     
 
       filecontent = String.new( @patterncontent )
 
       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 130: Line 381:
 
      
 
      
 
   end
 
   end
 +
 
    
 
    
 
   #Running
 
   #Running
Line 148: Line 400:
 
     @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 (
Line 155: Line 407:
 
     yield
 
     yield
 
      
 
      
     batchfoot = <<FOOT
+
     batchfoot = &lt;&lt;FOOT
 
     )
 
     )
 
     pause
 
     pause
Line 170: Line 422:
 
   def usesAGenericMohidtoolBatchfile(mohidtool, batchfilename, configfilename)
 
   def usesAGenericMohidtoolBatchfile(mohidtool, batchfilename, configfilename)
 
     usesTheFollowingBatchfileNameAndBlock(batchfilename){
 
     usesTheFollowingBatchfileNameAndBlock(batchfilename){
       @batch = <<BATCH
+
       @batch = &lt;&lt;BATCH
 
       copy %%i #{configfilename}
 
       copy %%i #{configfilename}
 
       #{mohidtool}
 
       #{mohidtool}
Line 192: Line 444:
 
end
 
end
  
class IsTheActionToPerformWithFiles < IsTheActionToPerformWith
+
class IsTheActionToPerformWithFiles &lt; IsTheActionToPerformWith
 
    
 
    
 
   def initialize(patternfilename, listofsubsfilename)
 
   def initialize(patternfilename, listofsubsfilename)
Line 218: Line 470:
 
if __FILE__ == $0
 
if __FILE__ == $0
 
    
 
    
mycontent = <<CONVERTTOHDF5ACTION
+
mycontent = &lt;&lt;CONVERTTOHDF5ACTION
<begin_file>
+
&lt;begin_file&gt;
 
ACTION                  : GLUES HDF5 FILES
 
ACTION                  : GLUES HDF5 FILES
  
 
OUTPUTFILENAME          : MOHID_WATER_01.hdf5
 
OUTPUTFILENAME          : MOHID_WATER_01.hdf5
 
   
 
   
<<begin_listofsubs>>
+
&lt;&lt;begin_listofsubs&gt;&gt;
 
..\\Extraction\\Stride_WaterProperties_1.hdf5
 
..\\Extraction\\Stride_WaterProperties_1.hdf5
 
..\\Extraction\\Stride_WaterProperties_2.hdf5
 
..\\Extraction\\Stride_WaterProperties_2.hdf5
<<end_listofsubs>>
+
&lt;&lt;end_listofsubs&gt;&gt;
<end_file>
+
&lt;end_file&gt;
 
CONVERTTOHDF5ACTION
 
CONVERTTOHDF5ACTION
  
mylistofsubs = <<listofsubs
+
mylistofsubs = &lt;&lt;listofsubs
 
_(01) s_(1). s_(2). (WATER) (WaterProperties)
 
_(01) s_(1). s_(2). (WATER) (WaterProperties)
 
   01      1        2    WATER  WaterProperties
 
   01      1        2    WATER  WaterProperties
Line 246: Line 498:
  
 
   ## 2 Generate new files ##########
 
   ## 2 Generate new files ##########
   glue.usesTransformedFilesNamedAfter("GlueAction")
+
   glue.transformsInto("GlueAction")
 
    
 
    
 
   ## 3 Generate runscript ##########
 
   ## 3 Generate runscript ##########
 
   #You can easily customize the batchfile main loop ...
 
   #You can easily customize the batchfile main loop ...
 
   glue.usesTheFollowingBatchfileNameAndBlock("GlueAllHdf5.bat") {
 
   glue.usesTheFollowingBatchfileNameAndBlock("GlueAllHdf5.bat") {
     glue.batch.replace <<BATCH
+
     glue.batch.replace &lt;&lt;BATCH
 
       copy %%i ConvertToHdf5Action.dat
 
       copy %%i ConvertToHdf5Action.dat
 
       ConvertToHdf5.exe
 
       ConvertToHdf5.exe

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