class Arquivo::C118dir

permite processar e arquivar pasta com documentos c118

permite processar e arquivar pasta com documentos c118

Attributes

contem[R]

@return [Symbol] conteudo da pasta

dados[R]

@return (see obtem_dados)

item[R]

@return [String] documento c118

items[R]

@return [Enumerator] items dentro duma pasta

local[R]

@return [String] local da pasta

noiseprof[R]

@return (see obtem_noiseprof)

nome[R]

@return [String] nome ficheiro de arquivo

opcoes[R]

@return [Hash] parametrizar JPG, MINUTA

Public Class Methods

new(dir, opt) click to toggle source

@param pasta (see CLI#dir) @param [Hash] opt parametrizar JPG, MINUTA @option opt [Numeric] :fuzz (29) trim jpg N-1, escolhe menor -> scanned pdf @option opt [Numeric] :quality (15) compress jpg N% -> scanned pdf (less=low quality) @option opt [Numeric] :threshold (9) limiar maximo para silencio, 0% = silencio puro @option opt [Numeric] :sound (1) segundos de som para terminar silencio @option opt [Numeric] :amount (0.00001) qtd ruido a ser removido, @option opt [Numeric] :rate (16) sample rate - radio-16k, CD-44.1k, PC-48k, pro-96k @return [C118dir] pasta de documentos c118

# File lib/arquivo/noise.rb, line 41
def initialize(dir, opt)
  c = Dir.glob(File.join(dir, '*'))
  @local = dir
  @items = c.each
  @nome = File.basename(dir, File.extname(dir)) + '-' +
          Date.today.strftime('%Y%m%d')
  @opcoes = opt
  @contem = obtem_conteudo(c)
end

Public Instance Methods

cmd_silencio(seg, thr) click to toggle source

@param [Array<String, Float, String>] seg segmento, duracao, file silencio @param thr (see maximo_silencio) @return [String] comando para cortar silencio inicial sum segmento

# File lib/arquivo/noise.rb, line 101
def cmd_silencio(seg, thr)
  ";sox #{seg[0]} #{seg[2]} silence 1 #{opcoes[:sound]}t #{thr}% #{O2}"
end
cria_noiseprof(seg) click to toggle source

@param [Array<String, Float>] seg segmento, duracao silencio inicial @return [String] perfil sonoro do silencio inicial dum segmento

# File lib/arquivo/noise.rb, line 113
def cria_noiseprof(seg)
  return unless seg[1] > opcoes[:sound]

  o = "tmp/noiseprof-#{File.basename(seg[0], File.extname(seg[0]))}"
  # obter noiseprof do silencio no inicio
  system "sox #{seg[0]} -n trim 0 #{seg[1]} noiseprof #{o} #{O2}"

  # so noiseprof validos sao devolvidos
  @noiseprof = File.size?(o).positive? ? o : nil
end
duracao(audio) click to toggle source

@param [String] audio ficheiro de audio @return [Float] duracao ficheiro audio em segundos

# File lib/arquivo/noise.rb, line 132
def duracao(audio)
  `soxi -V0 -D #{audio} #{O1}`.to_f
end
duracao_silencio(seg) click to toggle source

@param seg (see cmd_silencio) @return [Float] duracao silencio em segundos

# File lib/arquivo/noise.rb, line 107
def duracao_silencio(seg)
  (seg[1] - duracao(seg[2])).round(2, half: :down)
end
maximo_silencio(lsg, thr) click to toggle source

@param [Array] lsg lista segmentos audio com duracoes e file silencio @param [Numeric] thr limiar para silencio em processamento @return [Array<String, Float>] segmento com maior duracao silencio inicial

# File lib/arquivo/noise.rb, line 93
def maximo_silencio(lsg, thr)
  system lsg.inject('') { |s, e| s + cmd_silencio(e, thr) }[1..-1]
  lsg.map { |e| [e[0], duracao_silencio(e)] }.max_by { |_, s| s }
end
next_item() click to toggle source

@return [String] proximo item dentro da pasta

# File lib/arquivo/dir.rb, line 66
def next_item
  @item = items.next
rescue StopIteration
  @item = nil
end
noisy?(sin, thr) click to toggle source

@param [Float] sin duracao silencio @param thr (see maximo_silencio) @return [Boolean] segmento audio tem som ou silencio no inicio

# File lib/arquivo/noise.rb, line 86
def noisy?(sin, thr)
  thr < opcoes[:threshold] && sin <= opcoes[:sound]
end
obtem_conteudo(fls) click to toggle source

Agrupa conteudo duma pasta segundo tipos de documentos validos

@param [Array] fls lista items duma pasta @return [Symbol] tipo de conteudo @example contem

:fsc scq
:fsg minutas
:frc recibos
:fft faturas
:fex extratos
# File lib/arquivo/noise.rb, line 61
def obtem_conteudo(fls)
  t = fls.group_by { |f| File.ftype(f)[0] + File.basename(f)[0, 2] }.keys
  return unless t.size == 1 && DT.include?(t[0].to_sym)

  t[0].to_sym
end
obtem_dados() click to toggle source

@!group dados folhas-calculo c118 @return [Hash] dados oficiais para classificacao de faturas e recibos

# File lib/arquivo/dir.rb, line 74
def obtem_dados
  @dados = {}
  # somente faturas e recibos necessitam reclassificacao
  return unless %i[fft frc].include?(contem)

  # folha c118-contas
  s = '1PbiMrtTtqGztZMhe3AiJbDS6NQE9o3hXebnQEFdt954'
  @dados = C118sheets.new.folhas
                     .get_spreadsheet_values(s, contem.to_s + '!A2:E')
                     .values.group_by { |k| k[0][/\w+/] }
rescue StandardError
  @dados = {}
end
obtem_noiseprof() click to toggle source

@!group perfil silencio @return [String] perfil do maior silencio inicial de todos segmentos audio

# File lib/arquivo/noise.rb, line 70
def obtem_noiseprof
  return unless contem == :fsg

  l = obtem_segmentos
  return unless l.size.positive?

  t = -1
  m = ['', 0]
  m = maximo_silencio(l, t += 1) while noisy?(m[1], t)

  cria_noiseprof(m)
end
obtem_segmentos() click to toggle source

@return [Array] lista segmentos audio com duracoes e file silencio

# File lib/arquivo/noise.rb, line 125
def obtem_segmentos
  AT.map { |e| Dir.glob(File.join(local, 'sg*' + e)) }.flatten
    .map { |s| [s, duracao(s), "tmp/thr-#{File.basename(s)}"] }
end
processa_file(ext) click to toggle source

processa ficheiro JPG, PDF ou AUDIO

@param [String] ext tipo ficheiro

# File lib/arquivo/dir.rb, line 44
def processa_file(ext)
  opt = opcoes
  case ext
  when '.jpg' then C118jpg.new(item, opt).processa_jpg(dados)
  when '.pdf' then C118pdf.new(item, opt).processa_pdf(dados)
  when *AT    then C118mp3.new(item, opt).processa_mp3(noiseprof)
  else
    puts "erro: #{ext} nao posso processar este tipo de dicheiro"
  end
end
processa_fim(num) click to toggle source

cria ficheiros finais para arquivo

@param [Numeric] num numero de documentos dentro do arquivo

# File lib/arquivo/dir.rb, line 26
def processa_fim(num)
  return unless num.positive?

  cmd = if contem == :fsg
          "rm -f #{nome}.*;sox tmp/zip/* #{nome}.mp3"
        else
          "rm -f #{nome}.*;pdftk tmp/stamped* cat output #{nome}.pdf"
        end
  system cmd + ";cd tmp/zip;tar cf ../../#{nome}.tar *" \
               ";cd ../..;gzip --best #{nome}.tar" \
               ';rm -rf tmp'

  puts "#{nome} (#{num})"
end
processa_items() click to toggle source

@!group processamento processa items duma pasta

# File lib/arquivo/dir.rb, line 10
def processa_items
  n = 0
  while next_item
    if File.ftype(item) == 'directory'
      C118dir.new(item, opcoes).processa_pasta
    else
      processa_file(File.extname(item).downcase)
      n += 1
    end
  end
  processa_fim(n)
end
processa_pasta() click to toggle source

processa conteudo duma pasta

# File lib/arquivo/dir.rb, line 56
def processa_pasta
  if contem
    system 'mkdir -p tmp/zip'
    obtem_dados
    obtem_noiseprof
  end
  processa_items
end