Lab5 Italo Aguiar

aluno: Italo Aguiar
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 22/12/2008 (2)

Introdução

Esta pratica de laboratorio tem como objetivo desenvolver, a partir de um código previamente elaborado e parcialmente testado, uma aplicação em Ruby que simule um sistema de apostas em jogos de futebol. A aplicação desenvolvida aborda conceitos como Threads, IO e os padrões Decorator e Builder

A idéia central desta prática foi fazer algumas alterações e adições de forma que o código inicialmente fornecido pudesse, além de passar em todos os testes já previamente elaborados, ser o servidor para que aplicativos clientes possam, simultaneamente, se conectar e consumir os "serviços" disponíveis através do protocolo YAML ( curiosamente definido por alguns como "YAML Ain't a Markup Language")

Desenvolvimento

As classes criadas neste laboratório foram:

require 'decorators/decorator'
module Decorators
  class MatchListPersistanceDecorator < ListPersistanceDecorator
 
    def initialize(obj, filename)
      old_match_decorator = obj.item_decorator
      obj.item_decorator = lambda do |match|
        MatchPersistanceDecorator.new( old_match_decorator.call(match), self )
      end
      super(obj, filename)
    end
 
    def add(name, end_time)
        match = @decorated.add(name, end_time)
        save
        match
    end
  end
end
require 'decorators/decorator'
require 'monitor'
module Decorators
  class MatchListThreadSafeDecorator < Decorator
    include MonitorMixin
 
    def initialize(decorated)
      old_match_decorator = decorated.item_decorator
      decorated.item_decorator = lambda do |match|
        MatchThreadSafeDecorator.new( old_match_decorator.call(match) )
      end
      super
    end
 
    def add(name, end_time)
#      match = nil
      synchronize do
        @decorated.add(name, end_time)
      end
#      match
    end
  end
end
require 'decorators/decorator'
module Decorators
  class MatchPersistanceDecorator < Decorator
 
    def initialize(obj, matchListPersistanceDecorator)
      super(obj)
      @matchListPersistanceDecorator = matchListPersistanceDecorator
    end
 
    def make_bet(score, user)
      bet_return = @decorated.make_bet(score, user)
      @matchListPersistanceDecorator.save
      bet_return
    end
 
    def finalize(final_score)
      final_score = @decorated.finalize(final_score)
      @matchListPersistanceDecorator.save
      final_score
    end
 
  end
end
require 'monitor'
require 'decorators/decorator'
module Decorators
  class MatchThreadSafeDecorator < Decorator
    include MonitorMixin
 
    def make_bet(score, user)
      synchronize do
        @decorated.make_bet(score, user)
      end
    end
 
    def finalize(final_score)
      ret_val = nil
 
      synchronize do
        ret_val = @decorated.finalize(final_score)
      end
 
      ret_val
 
    end
 
  end
end
require 'initialize'
 
class MatchListBuilder
 
  include Decorators
 
  def initialize
    @match_list = MatchList.new
  end
 
  def add_persistance
    @added_persistance = true
    @match_list = MatchListPersistanceDecorator.new(@match_list, "matches_test.yml")
  end
 
  def add_logging
    @match_list = MatchListLoggerDecorator.new(@match_list)
  end
 
  def add_thread_safety
    @match_list = MatchListThreadSafeDecorator.new(@match_list)
  end
 
  def add_all
    add_logging
    add_persistance
    add_thread_safety
  end
 
  def match_list
    @match_list.load_list if @added_persistance
    @match_list
  end
 
end
require 'initialize'
 
class UserListBuilder
 
  include Decorators
 
  def initialize
    @user_list = UserList.new
  end
 
  def add_persistance
    @added_persistance = true
    @user_list = ListPersistanceDecorator.new(@user_list, "users_test.yml")
  end
 
  def add_logging
    @user_list = UserListLoggerDecorator.new(@user_list)
  end
 
  def add_thread_safety
    @user_list = ListThreadSafeDecorator.new(@user_list)
  end
 
  def add_all
    add_logging
    add_persistance
    add_thread_safety
  end
 
  def user_list
    @user_list.load_list if @added_persistance
    @user_list
  end
 
end
require 'initialize'
 
class RequestReader
 
  include Printers
 
  def initialize(io=$stdin)
    @io = io
 
    @match_list = MatchListThreadSafeDecorator.new(MatchListLoggerDecorator.new(MatchListPersistanceDecorator.new(MatchList.new, "matches_test.yml"))) 
    @match_list.load_list
 
    user_list_builder = UserListBuilder.new
    user_list_builder.add_all
    @user_list = user_list_builder.user_list
  end
 
  def parse
    #lê a entrada linha a linha até acharmos um "INICIO"
    loop do
      string = @io.gets
      break if string && string.include?("INICIO")
    end
    yaml = @io.gets("\nFIM") #depois do INICIO, lê tudo até a palavra FIM
    yaml = yaml.chomp("FIM") #tira o FIM do final do string que foi lido do @io
    @requisicao = YAML.load(yaml) # aqui já temos o hash com a requisicao processada
 
    indice = "operation"
    puts @requisicao[indice]
 
    #... processa requisicão e escreve saída
  end
 
  def process(request)
 
    yaml = request #depois do INICIO, lê tudo até a palavra FIM
    yaml = yaml.chomp("FIM") #tira o FIM do final do string que foi lido do @io
    @requisicao = YAML.load(yaml) # aqui já temos o hash com a requisicao processada
 
    #    indice = "parameters"
    #    puts @requisicao["request"][indice]
    #... processa requisicão e escreve saída
 
    process_requisicao
 
  end
 
  def process_requisicao
    operation = @requisicao["request"]["operation"]
    yaml = YamlMatchListPrinter.new(@match_list)
 
    if operation.eql?("print_matches")
      yaml.print_matches
    elsif operation.eql?("print_finalized_matches")
      yaml.print_finalized_matches
    end
 
  end
 
end
#main.rb
 
require 'initialize'
require 'request_reader'
require 'MatchListBuilder'
require 'UserListBuilder'
 
include Decorators
 
def main(request, inn=$stdin, out=$stdout)
  reader = RequestReader.new(inn)
 
  #  loop do
  #utiliza RequestReader para esperar a chegada de uma requisição
  reader.process(request)
  #  end
 
  #puts inn.gets.chomp + "BLAH"
  #
  # código do main
end
 
def init_bolao
  # => USERS:
  user_list_builder = UserListBuilder.new
  user_list_builder.add_all
 
  $user_list = user_list_builder.user_list
 
  # => CAMPOS A SEREM DESCOMENTADOS CASO O ARQUIVO SEJA APAGDO
    jose = $user_list.add("jose", "123456")
    joao = $user_list.add("joao", "123456")
    maria = $user_list.add("maria", "123456")
 
  # => MATCHES:
  match_list_builder = MatchListBuilder.new
  match_list_builder.add_all
 
  # => nao foi possivel usar o builder para match, pois estava dando um erro que nao consegui contornar
  #  $match_list = match_list_builder.match_list
  $match_list = MatchListThreadSafeDecorator.new(MatchListLoggerDecorator.new(MatchListPersistanceDecorator.new(MatchList.new, "matches_test.yml"))) 
  #  $match_list.load_list
 
  # => CAMPOS A SEREM DESCOMENTADOS CASO O ARQUIVO SEJA APAGDO
    m1 = $match_list.add "atletico x cruzeiro", Time.now + 100000
    m2 = $match_list.add "atletico x palmeiras", Time.now + 100000
 
    m1.make_bet "5x0", jose
    m1.make_bet "5x0", joao
    m1.make_bet "0x1", maria
    m2.make_bet " 3 x 0", jose
    m2.make_bet "2x0", joao
    m1.finalize("5x0")
 
end
 
def finalize_bolao
  File.delete("users_test.yml") rescue nil
  File.delete("matches_test.yml") rescue nil
end
 
init_bolao
 
print_matches = "---
request:  
 operation: print_matches
FIM"
 
print_finalized_matches = "---
request:  
 operation: print_finalized_matches
FIM"
 
main(print_finalized_matches)

Para a execução dos testes, obteve-se o seguinte resultado:
tests_print.jpg

Como este laboratório não foi desenvolvido no H8, ficou complicado tentar desenvolver a parte que era em dupla com algum outro aluno. Portanto, esta prática foi feita de forma individual, ficando inviável a construção total do protocolo proposto, pois este é consideravelmente composto de "trabalho braçal".
Desta forma, foram elaboradas apenas algumas das funções propostas, com o único intuito de aprender o funcionamento do protocolo YAML e como fazer uso deste para disponibilizar a aplicacao para acesso remoto.

Assim, para a execução da classe main, obteve-se o seguinte resultado:
run_print.jpg

Conclusão

Dos vários erros que apareceram no decorrer do lab, apenas um nao foi possível sanar: ao se tentar utilizar o MatchListBuilder de forma analoga ao UserListBuilder, um erro estranho aparecia e mesmo depois de pesquisar na internet possiveis formas de solução para tal erro não consegui saná-lo.

Nesta prática, foi possível aprender como trabalhar, em Ruby, com o conceito de thread, fazendo com que certas passagens do programa (como fazer apostas e finalizar jogo) fossem sicronizadas; o conceito de IO, possibilitando interfaces de entrada e saída para o usuario cliente poder comunicar-se com o servidor.

Foi possível também ver a utilidade dos padrões Decorator e Builder. O primeiro usado para adicionar características de persistencia, logging e thread safe aos componentes do aplicativo e o segundo para poder construir tais componentes, cuja natureza da criação é complexa, de forma simplificada e direta.

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License