foot_stats_simulator 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,185 @@
1
+ # encoding: UTF-8
2
+
3
+ class SimulatorTimeline
4
+ module LoremMessages
5
+
6
+ def not_started_message
7
+ "#{ home_team.full_name } X #{ visitor_team.full_name }, aqui no estádio #{ match.stadium }, esse jogo promete!"
8
+ end
9
+
10
+ def first_period_message
11
+ "Árbitro #{match.referee} apita início da partida, #{ home_team.full_name } e #{ visitor_team.full_name } entram em campo com tudo!"
12
+ end
13
+
14
+ def first_interval_message
15
+ "Fim do primeiro tempo #{ home_team.full_name } #{ home_score } X #{ visitor_team.full_name } #{ visitor_score }, vamos ver se no segundo tempo esses jogadores param de moleza... estão parecendo programadores!"
16
+ end
17
+
18
+ def second_period_message
19
+ "Início do segundo tempo, <%= current_player %> tenta dar o primeiro passe em direção ao campo adversário, mas pisa na bola e escorrega."
20
+ end
21
+
22
+ def second_interval_message
23
+ "Esse jogo está muito morto... Vamos ver se ele se decide após o segundo intervalo."
24
+ end
25
+
26
+ def first_prorrogation_message
27
+ "Jogo disputado, #{ home_team.full_name } X #{ visitor_team.full_name }, quem sabe esse jogo se decide nessa prorrogação!"
28
+ end
29
+
30
+ def third_interval_message
31
+ "Uma pequena pausa, em breve os jogadores voltam ao campo."
32
+ end
33
+
34
+ def second_prorrogation_message
35
+ "Morte súbita! Os jogadores já estão quase mortos de cansaço..."
36
+ end
37
+
38
+ def penalties_message
39
+ "Agora é tudo ou nada... Decisão nos penaltis! <%= current_player %> já se posiciona para o primeiro chute a gol."
40
+ end
41
+
42
+ def finished_message
43
+ "Fim de jogo! #{ home_team.full_name } #{ home_score } X #{ visitor_team.full_name } #{ visitor_score }, boa noite!"
44
+ end
45
+
46
+ def stopped_match_message
47
+ [
48
+ "Partida parada, <%= current_home_player %> chuta o saco de <%= current_visitor_player %>, #{ visitor_team.full_name } se mobiliza.",
49
+ "Partida parada, <%= trolled_person %> invade o campo e rouba a bola.",
50
+ "Partida parada, <%= trolled_person %> invade o campo e ataca a bandeirinha gostosa.",
51
+ ]
52
+ end
53
+
54
+ def canceled_message
55
+ [
56
+ "Partida cancelada, os refletores realmente não estão funcionando nessa noite!",
57
+ "Partida cancelada, a confusão é geral, os torcedores invadem o campo e a polícia tem que intervir!",
58
+ "Partida cancelada, o árbitro #{match.referee} é atacado por um cão raizoso que invadiu o campo, e é levado para tomar uma anti-rábica"
59
+ ]
60
+ end
61
+
62
+ def goal_message
63
+ "GOL! #{ home_team.full_name } #{ home_score } X #{ visitor_team.full_name } #{ visitor_score } - <%= current_player %> <%= goal_kind %> para o <%= player_team %>"
64
+ end
65
+
66
+ def goal_kind_message
67
+ [
68
+ 'mata no peito, domina e chuta no ângulo! Gol',
69
+ 'cobra a falta com precisão e marca o gol',
70
+ 'chuta, e o goleiro dá um frango! Entre as pernas! Gol',
71
+ 'dá um peixinho e finaliza'
72
+ ]
73
+ end
74
+
75
+ def lorem_message
76
+ cornerkick_message + sidekick_message + foul_message + funny_message
77
+ end
78
+
79
+ def funny_message
80
+ [
81
+ 'E agora na arquibancada, alguém acaba de mostrar um cartaz escrito "CALA A BOCA GALVÃO".',
82
+ 'O que é isso? O <%= trolled_person %> está dando uma de técnico da seleção alemã enfiando o dedo no nariz!',
83
+ 'Futebol sem preconceitos: Na arquibancada, Richarlyson e seu novo namorado <%= trolled_person %>, acompanham esse jogo abraçadinhos!',
84
+ 'Uma ativista peladona invade o campo para protestar contra o aquecimento global. <%= trolled_person %> irritado, a retira do campo.'
85
+ ]
86
+ end
87
+
88
+ def cornerkick_message
89
+ [
90
+ "<%= current_home_player %> mandou a bola pra escaneio, <%= current_visitor_player %> parte para a cobrança.",
91
+ "<%= current_visitor_player %> mandou a bola pra escaneio, <%= current_home_player %> parte para a cobrança."
92
+ ]
93
+ end
94
+
95
+ def sidekick_message
96
+ [
97
+ "Lateral a favor do <%= home_team.full_name %>, <%= current_home_player %> é quem vai cobrar.",
98
+ "Lateral a favor do <%= visitor_team.full_name %>, <%= current_visitor_player %> é quem vai cobrar."
99
+ ]
100
+ end
101
+
102
+ def foul_message
103
+ [
104
+ "<%= current_player %> recebeu uma falta porque <%= infringement %>."
105
+ ]
106
+ end
107
+
108
+ def substitution_message
109
+ [
110
+ "<%= new_player %> entra em campo no lugar de <%= leaving_player %>.",
111
+ "<%= leaving_player %> já deu o que tinha que dar, agora é <%= new_player %> que entra em campo."
112
+ ]
113
+ end
114
+
115
+ def card_message
116
+ "<%= current_player %> recebeu um cartão <%= card_kind %> porque <%= infringement %>"
117
+ end
118
+
119
+ def card_kind_message
120
+ [
121
+ 'amarelo',
122
+ 'vermelho'
123
+ ]
124
+ end
125
+
126
+ def infringement_message
127
+ [
128
+ 'xingou a mãe do juíz de quenga! Como ele descobriu?',
129
+ '<%= a_knock %> <%= current_player %>.',
130
+ 'chutou <%= an_animal %> que invadiu o campo.',
131
+ 'saiu correndo sem camisa, com no peito escrito "<%= trolled_person.upcase %> EU TE AMO!".'
132
+ ]
133
+ end
134
+
135
+ def a_knock_message
136
+ [
137
+ 'deu um chute no saco do',
138
+ 'deu um carrinho por tráz no',
139
+ 'deu uma voadora no peito do',
140
+ 'apertou os peitinhos do'
141
+ ]
142
+ end
143
+
144
+ def an_animal_message
145
+ [
146
+ 'uma capivara',
147
+ 'um urubú',
148
+ "o <%= trolled_person %> peladão",
149
+ 'a mãe do juíz'
150
+ ]
151
+ end
152
+
153
+ def trolled_person_message
154
+ [
155
+ 'Ruschel', 'Dayyán', 'Ettore', 'Cruz',
156
+ 'Enio', 'Lucas', 'Tomas',
157
+ 'Akita', 'Pisano', 'Abilheira'
158
+ ]
159
+ end
160
+
161
+ def current_home_player_message
162
+ current_home_players.map(&:nickname)
163
+ end
164
+
165
+ def current_visitor_player_message
166
+ current_visitor_players.map(&:nickname)
167
+ end
168
+
169
+ def home_player_message
170
+ home_players.map(&:nickname)
171
+ end
172
+
173
+ def visitor_player_message
174
+ visitor_players.map(&:nickname)
175
+ end
176
+
177
+ def player_message
178
+ all_players.map(&:nickname)
179
+ end
180
+
181
+ def current_player_message
182
+ all_current_players.map(&:nickname)
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,26 @@
1
+ class SimulatorTimeline
2
+ class Minute
3
+ def initialize(timeline, period_time, minute)
4
+ @timeline, @period_time, @minute = timeline, period_time, minute
5
+ yield(self) if block_given?
6
+ end
7
+
8
+ def event_handler
9
+ @event_handler ||= EventHandler.new(@timeline, @period_time, @minute)
10
+ end
11
+
12
+ def reached_time?
13
+ @timeline.current_period_time > @period_time || (
14
+ @timeline.current_period_time == @period_time && @timeline.current_minute >= @minute
15
+ )
16
+ end
17
+
18
+ def method_missing(method_name, *args, &block)
19
+ if event_handler.respond_to?(method_name)
20
+ event_handler.public_send(method_name, *args, &block) if reached_time?
21
+ else
22
+ super(method_name, *args, &block)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,39 @@
1
+ class SimulatorTimeline
2
+ class NarrationEvent < SimulatorTimeline::Event
3
+ attr_reader :message, :source_id, :moment, :reference
4
+
5
+ def initialize(event_handler, timeline, period_time, minute, options = {})
6
+ super(event_handler, timeline, period_time, minute, options)
7
+ @message, @reference = options.values_at :message, :reference
8
+ @source_id = @timeline.timeline_rand(10**7)+1
9
+ @moment = format "%02d:%02d", period_time, @timeline.timeline_rand(60)
10
+ end
11
+
12
+ def to_foot_stats
13
+ {
14
+ "@Id" => @source_id,
15
+ "IdEquipe" => "",
16
+ "NomeEquipe" => "",
17
+ "IdJogador" => "",
18
+ "NomeJogador" => "",
19
+ "Periodo" => SimulatorMatch::STATUS_MAP[SimulatorMatch::STATUSES[@period_time]],
20
+ "Momento" => @moment,
21
+ "Descricao" => @message,
22
+ "Acao" => ""
23
+ }
24
+ end
25
+
26
+ def self.remove(timeline, reference)
27
+ timeline.narration.delete_if{ |event| event.reference == reference }
28
+ end
29
+
30
+ def self.to_foot_stats(array_of_narrations)
31
+ fuck_collection 'Narracao', array_of_narrations.map(&:to_foot_stats)
32
+ end
33
+
34
+ protected
35
+ def apply_event
36
+ @timeline.narration << self
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,29 @@
1
+ class SimulatorTimeline
2
+ class Period
3
+ def initialize(timeline, period, options={})
4
+ @timeline, @period = timeline, period
5
+ add_narration(options) if @timeline.current_period_time >= period_time
6
+ end
7
+
8
+ def period_time
9
+ SimulatorMatch::STATUS_SEQUENCE[@period] || @period.to_i
10
+ end
11
+
12
+ def at(minute, &block)
13
+ Minute.new @timeline, period_time, minute, &block
14
+ end
15
+
16
+ protected
17
+ def add_narration(options)
18
+ if options[:narration]
19
+ event_handler.narration options[:narration]
20
+ else
21
+ event_handler.narration @period
22
+ end
23
+ end
24
+
25
+ def event_handler
26
+ EventHandler.new(@timeline, SimulatorMatch::STATUS_SEQUENCE[@period], 0)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,65 @@
1
+ class SimulatorTimeline
2
+ class PlayerEvent < SimulatorTimeline::Event
3
+ attr_accessor :playing
4
+
5
+ attr_reader :player, :reference, :substituted
6
+
7
+ def initialize(event_handler, timeline, period_time, minute, options = {})
8
+ @player, @reference, @status, substituted_index = options.values_at :player, :reference, :status, :substituted
9
+ @playing = true
10
+ @status ||= "Titular"
11
+ set_substituted(substituted_index) if substituted_index
12
+ super(event_handler, timeline, period_time, minute, options)
13
+ end
14
+
15
+ def to_foot_stats
16
+ {
17
+ "@Jogador" => @player.full_name,
18
+ "@IdJogador" => @player.source_id,
19
+ "@Status" => @status,
20
+ "@Substituto" => (@substituted || ''),
21
+ "@Periodo" => (@substituted ? SimulatorMatch::STATUS_MAP[SimulatorMatch::STATUSES[@period_time]] : 'Nenhum'),
22
+ "@Minuto" => @minute.to_s
23
+ }
24
+ end
25
+
26
+ def self.remove(timeline, reference)
27
+ timeline.current_home_players.delete_all{ |event| event.reference == reference }
28
+ timeline.current_visitor_players.delete_all{ |event| event.reference == reference }
29
+ end
30
+
31
+ def self.to_foot_stats(array_of_players)
32
+ fuck_collection 'Jogador', array_of_players.map(&:to_foot_stats)
33
+ end
34
+
35
+ def method_missing(method_name, *args, &block)
36
+ if @player.respond_to?(method_name)
37
+ @player.public_send(method_name, *args, &block)
38
+ else
39
+ super(method_name, *args, &block)
40
+ end
41
+ end
42
+
43
+ protected
44
+ def set_substituted(substituted_index)
45
+ player_collection = if @player.simulator_team == @timeline.home_team
46
+ @timeline.current_home_players
47
+ else
48
+ @timeline.current_visitor_players
49
+ end
50
+ substituted = player_collection.find_all{ |p| p.playing }[substituted_index]
51
+ substituted.playing = false
52
+ @substituted = substituted.full_name
53
+
54
+ event_handler.narration :substitution, new_player: @player.nickname, leaving_player: @substituted
55
+ end
56
+
57
+ def apply_event
58
+ if @player.simulator_team == @timeline.home_team
59
+ @timeline.current_home_players << self
60
+ else
61
+ @timeline.current_visitor_players << self
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,45 @@
1
+ class SimulatorTimeline
2
+ class States
3
+ def initialize(timeline)
4
+ @timeline = timeline
5
+ yield(self)
6
+ finish_initialize
7
+ end
8
+
9
+ def add_transition(state, time, options = {})
10
+ @timeline.states << [time, state, options]
11
+ end
12
+
13
+ def method_missing(method_name, *args, &block)
14
+ if SimulatorMatch::STATUS_SEQUENCE[method_name]
15
+ add_transition(method_name, args.first)
16
+ else
17
+ super(method_name, *args, &block)
18
+ end
19
+ end
20
+
21
+ protected
22
+ def finish_initialize
23
+ @timeline.states.sort!
24
+ insert_not_started_if_missing
25
+ set_current_period_and_minute
26
+ end
27
+
28
+ def insert_not_started_if_missing
29
+ first_state = @timeline.states.first
30
+ if first_state.blank? || first_state[1] != :not_started
31
+ minute = first_state[0] - 1 rescue 0
32
+ @timeline.states.unshift [minute, :not_started, Hash.new]
33
+ end
34
+ end
35
+
36
+ def set_current_period_and_minute
37
+ delta = (Time.now - @timeline.match.date).to_i
38
+
39
+ seconds, state, options = @timeline.states.reverse.find{|seconds, state, options| delta > seconds } || [0, :not_started, Hash.new]
40
+
41
+ @timeline.current_period = state
42
+ @timeline.current_minute = (delta - seconds)/60
43
+ end
44
+ end
45
+ end
data/config/routes.rb CHANGED
@@ -1,14 +1,12 @@
1
1
  FootStatsSimulator::Engine.routes.draw do
2
2
 
3
-
4
-
5
3
  match 'ListaCampeonatos' => 'api#championship', via: :post, as: 'championship'
4
+ match 'ListaEquipesCampeonato' => 'api#championship_teams', via: :post, as: 'championship_teams'
5
+ match 'ListaJogadoresEquipe' => 'api#team_players', via: :post, as: 'team_players'
6
6
  match 'ListaClassificacao' => 'api#championship_classification', via: :post, as: 'championship_classification'
7
7
  match 'ListaPartidas' => 'api#championship_match', via: :post, as: 'championship_match'
8
8
  match 'ListaPartidasRodada' => 'api#championship_round_match', via: :post, as: 'championship_round_match'
9
- match 'ListaEquipesCampeonato' => 'api#championship_teams', via: :post, as: 'championship_teams'
10
9
  match 'AoVivo' => 'api#live_match', via: :post, as: 'live_match'
11
10
  match 'Narracao' => 'api#match_narration', via: :post, as: 'match_narration'
12
- match 'ListaJogadoresEquipe' => 'api#team_players', via: :post, as: 'team_players'
13
11
 
14
12
  end
@@ -1,4 +1,16 @@
1
- require "foot_stats_simulator/engine"
1
+ require 'foot_stats_simulator/engine'
2
+ require 'foot_stats'
3
+
4
+ require 'faker'
5
+
6
+ require 'singleton'
2
7
 
3
8
  module FootStatsSimulator
9
+ attr_accessor :timelines_dir
10
+
11
+ include Singleton
12
+
13
+ def self.method_missing(method_name, *args, &block)
14
+ instance.send method_name, *args, &block
15
+ end
4
16
  end
@@ -1,4 +1,4 @@
1
- ActiveRecord::Migration.create_table :simulator_championship do |t|
1
+ ActiveRecord::Migration.create_table :simulator_championships do |t|
2
2
  t.integer :source_id
3
3
  t.string :name
4
4
  t.boolean :has_classification
@@ -6,47 +6,57 @@ ActiveRecord::Migration.create_table :simulator_championship do |t|
6
6
  t.integer :total_rounds
7
7
  end
8
8
 
9
- ActiveRecord::Migration.create_table :simulator_team do |t|
9
+ ActiveRecord::Migration.create_table :simulator_teams do |t|
10
10
  t.integer :source_id
11
11
  t.string :full_name
12
12
  t.string :city
13
13
  t.string :country
14
14
  end
15
15
 
16
- ActiveRecord::Migration.create_table :simulator_player do |t|
17
- t.integer :source_id
18
- t.string :full_name
19
- t.string :nickname
16
+ ActiveRecord::Migration.create_table :simulator_championship_participations do |t|
17
+ t.references :simulator_championship
18
+ t.references :simulator_team
20
19
  end
21
20
 
22
- ActiveRecord::Migration.create_table :simulator_match do |t|
23
- t.integer :source_id
24
- t.string :date
25
- t.string :status
26
- t.string :referee
27
- t.string :stadium
28
- t.string :city
29
- t.string :state
30
- t.string :country
31
- t.string :has_statistic
32
- t.string :has_narration
33
- t.string :round
34
- t.string :phase
35
- t.string :cup
36
- t.string :group
37
- t.string :game_number
38
- t.boolean :live
39
- t.string :home_team
40
- t.string :home_team_name
41
- t.string :home_score
42
- t.string :home_penalties_score
43
- t.string :visitor_team
44
- t.string :visitor_team_name
45
- t.string :visitor_score
46
- t.string :visitor_penalties_score
21
+ ActiveRecord::Migration.create_table :simulator_players do |t|
22
+ t.references :simulator_team
23
+ t.integer :source_id
24
+ t.string :full_name
25
+ t.string :nickname
47
26
  end
48
27
 
49
- ActiveRecord::Migration.create_table :simulator_timeline do |t|
50
- t.integer :simulator_match_id
51
- t.string :timeline_name
28
+ ActiveRecord::Migration.create_table :simulator_matches do |t|
29
+ t.references :simulator_championship
30
+ t.integer :home_team_id
31
+ t.integer :visitor_team_id
32
+
33
+ t.string :timeline_name
34
+ t.string :timeline_status
35
+ t.decimal :timeline_random_seed
36
+
37
+ t.integer :source_id
38
+ t.time :date
39
+ t.string :status
40
+ t.string :referee
41
+ t.string :stadium
42
+ t.string :city
43
+ t.string :state
44
+ t.string :country
45
+ t.boolean :statistic
46
+ t.boolean :narration
47
+ t.integer :round
48
+ t.string :phase
49
+ t.string :cup
50
+ t.string :group
51
+ t.integer :game_number
52
+ t.boolean :live
53
+
54
+ t.string :home_team_name
55
+ t.integer :home_score
56
+ t.integer :home_penalties_score
57
+ t.string :visitor_team_name
58
+ t.integer :visitor_score
59
+ t.integer :visitor_penalties_score
60
+
61
+ t.timestamps
52
62
  end