pfa 1.0.1
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.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +8 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +46 -0
- data/README.md +156 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/assets/Manuel/ImageMagick.md +155 -0
- data/lib/assets/Manuel/Manuel-developer.md +50 -0
- data/lib/assets/fr/PFA_ABSOLUTE_DATA.yaml +212 -0
- data/lib/assets/fr/errors.yaml +107 -0
- data/lib/pfa/absolute_pfa.rb +25 -0
- data/lib/pfa/any_builder.rb +28 -0
- data/lib/pfa/constants.rb +24 -0
- data/lib/pfa/errors_manager.rb +14 -0
- data/lib/pfa/imagemagick_module.rb +551 -0
- data/lib/pfa/img_builder.rb +198 -0
- data/lib/pfa/node_time.rb +188 -0
- data/lib/pfa/pfa_element_module.rb +30 -0
- data/lib/pfa/relative_pfa.rb +191 -0
- data/lib/pfa/relative_pfa_datatime.rb +27 -0
- data/lib/pfa/relative_pfa_node.rb +238 -0
- data/lib/pfa/temporal_methods.rb +69 -0
- data/lib/pfa/version.rb +3 -0
- data/lib/pfa.rb +20 -0
- data/pfa.gemspec +34 -0
- data/pfa.jpg +0 -0
- metadata +147 -0
@@ -0,0 +1,198 @@
|
|
1
|
+
#
|
2
|
+
# Module de construction de l'image CVG
|
3
|
+
#
|
4
|
+
require_relative 'imagemagick_module'
|
5
|
+
require_relative 'any_builder'
|
6
|
+
module PFA
|
7
|
+
class RelativePFA
|
8
|
+
class ImgBuilder < AnyBuilder
|
9
|
+
|
10
|
+
attr_reader :code_image_magick
|
11
|
+
|
12
|
+
|
13
|
+
# Initialisation avant la construction
|
14
|
+
#
|
15
|
+
# On définit notamment toutes les constants PFA_WIDTH etc.
|
16
|
+
#
|
17
|
+
def init(**params)
|
18
|
+
params[:as].is_a?(Symbol) || params[:as].is_a?(Hash) || raise(PFAFatalError.new(101))
|
19
|
+
MagickPFA.define_dims_constants(params[:as])
|
20
|
+
end
|
21
|
+
|
22
|
+
def coef_pixels
|
23
|
+
@coef_pixels ||= calc_coefficient_pixels
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
##########################################
|
28
|
+
### MÉTHODE PRINCIPALE DE CONSTRUCTION ###
|
29
|
+
##########################################
|
30
|
+
# Construction de l'image du paradigme
|
31
|
+
#
|
32
|
+
# @param params [Hash]
|
33
|
+
# :as La chose à construire, permettant de définir les
|
34
|
+
# dimensions de l'image et les dimensions principales.
|
35
|
+
# Mettre :real_book ou :test pour des dimensions
|
36
|
+
# différentes et connu.
|
37
|
+
# Cf. le fichier any_builder.rb pour voir les valeurs
|
38
|
+
# possible.
|
39
|
+
#
|
40
|
+
def build(**params)
|
41
|
+
#
|
42
|
+
# Initialisation de la construction. On doit par exemple fournir
|
43
|
+
# les dimensions à utiliser à l'aide options[:as]
|
44
|
+
#
|
45
|
+
init(**params)
|
46
|
+
|
47
|
+
#
|
48
|
+
# Le PFA doit être défini au minimum et ses données doivent être
|
49
|
+
# valides.
|
50
|
+
#
|
51
|
+
pfa.valid?
|
52
|
+
|
53
|
+
#
|
54
|
+
#
|
55
|
+
# Détruire l'image si elle existe déjà
|
56
|
+
#
|
57
|
+
File.delete(image_path) if File.exist?(image_path)
|
58
|
+
|
59
|
+
#
|
60
|
+
# Construction du code pour Image Magick
|
61
|
+
# (tous les codes seront injectés dans @code_image_magick)
|
62
|
+
#
|
63
|
+
@code_image_magick = [MagickPFA.code_for_intro]
|
64
|
+
|
65
|
+
#
|
66
|
+
# Les titres des deux PFA
|
67
|
+
# (on peut utiliser n'importe quel noeud pour les afficher)
|
68
|
+
#
|
69
|
+
@code_image_magick << pfa.exposition.titre_pfa(false)
|
70
|
+
@code_image_magick << pfa.exposition.titre_pfa(true)
|
71
|
+
|
72
|
+
#
|
73
|
+
# Le fond, avec les actes
|
74
|
+
#
|
75
|
+
actes.each do |acte|
|
76
|
+
# acte.full_code_image_magick
|
77
|
+
# -- Cadre de la partie (acte) --
|
78
|
+
@code_image_magick << acte.act_box_code(true)
|
79
|
+
@code_image_magick << acte.act_box_code(false)
|
80
|
+
# --- Nomde l'acte --
|
81
|
+
@code_image_magick << acte.act_name_code(true)
|
82
|
+
@code_image_magick << acte.act_name_code(false)
|
83
|
+
# --- Horloge de l'acte ---
|
84
|
+
@code_image_magick << acte.horloge_code(false, nil)
|
85
|
+
@code_image_magick << acte.horloge_code(true, nil)
|
86
|
+
end
|
87
|
+
|
88
|
+
# --- Horloges de fin ---
|
89
|
+
#
|
90
|
+
# @note
|
91
|
+
# Peu importe le noeud qui est appelé
|
92
|
+
#
|
93
|
+
@code_image_magick << pfa.denouement.horloge_fin(false)
|
94
|
+
@code_image_magick << pfa.denouement.horloge_fin(true)
|
95
|
+
|
96
|
+
|
97
|
+
# --- IMPRESSION DES AUTRES NOEUDS/SÉQUENCES ---
|
98
|
+
#
|
99
|
+
# On passe en revue tous les autres éléments du paradigme réel
|
100
|
+
# et s'ils sont imprimable, on les ajoute.
|
101
|
+
@last_abs_left = nil
|
102
|
+
@last_left = nil
|
103
|
+
pfa.data.values.each do |node|
|
104
|
+
next if node.part? # déjà traité
|
105
|
+
next unless node.drawnable? # pas imprimable
|
106
|
+
# -- Mark et nom --
|
107
|
+
@code_image_magick << node.image_magick_code(false, @last_abs_left)
|
108
|
+
@code_image_magick << node.image_magick_code(true, @last_left)
|
109
|
+
# -- Les horloges --
|
110
|
+
@code_image_magick << node.horloge_code(false, @last_abs_left)
|
111
|
+
@code_image_magick << node.horloge_code(true, @last_left)
|
112
|
+
#
|
113
|
+
# On garde en mémoire les dimensions pour savoir si ça
|
114
|
+
# va manger dessus (overlay)
|
115
|
+
#
|
116
|
+
@last_abs_left = node.abs_left + [ MagickPFA::Horloge_Width[node.type]/2, MagickPFA::Label_Width[node.type]/2 ].max
|
117
|
+
@last_left = node.left + [ MagickPFA::Horloge_Width[node.type]/2, MagickPFA::Label_Width[node.type]/2 ].max
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
#
|
122
|
+
# Chemin d'accès au fichier final
|
123
|
+
# (en le protégeant)
|
124
|
+
#
|
125
|
+
@code_image_magick << "\"#{image_path.gsub(/ /, "\\ ")}\""
|
126
|
+
|
127
|
+
#
|
128
|
+
# On transforme le code ImageMagick en ajoutant des retours
|
129
|
+
# de chariot entre chaque section de code
|
130
|
+
#
|
131
|
+
@code_image_magick = @code_image_magick.join("\n")
|
132
|
+
|
133
|
+
# STDOUT.write "\n\ncmd à la fin =\n++++\n#{cmd}\n+++++\n".orange
|
134
|
+
|
135
|
+
#
|
136
|
+
# Mise de la commande sur une seule ligne
|
137
|
+
# (je ne parviens pas à mettre la commande sur plusieurs lignes,
|
138
|
+
# même avec la contre-balance…)
|
139
|
+
cmd_finale = @code_image_magick.split("\n").compact.join(" ")
|
140
|
+
|
141
|
+
|
142
|
+
# Pour débugger facilement, on met les numéros des lignes
|
143
|
+
|
144
|
+
cmd_debug = cmd_finale.split("\n").collect.with_index do |line, idx|
|
145
|
+
"#{idx + 1}: #{line.strip}"
|
146
|
+
end.join("\n")
|
147
|
+
# dbg "\n\nCommande finale\n#{cmd_debug}\n".bleu
|
148
|
+
|
149
|
+
#
|
150
|
+
# *** EXÉCUTION DE LA COMMANDE ***
|
151
|
+
#
|
152
|
+
res_err = `#{cmd_finale} 2>&1`
|
153
|
+
|
154
|
+
unless res_err.nil? || res_err.empty?
|
155
|
+
raise PFAFatalError.new(5001, **{error: res_err})
|
156
|
+
end
|
157
|
+
|
158
|
+
#
|
159
|
+
# L'image doit avoir été créée
|
160
|
+
#
|
161
|
+
File.exist?(image_path) || raise(PFAFatalError.new(5000, **{path: image_path}))
|
162
|
+
puts "Image #{image_path.inspect} produite avec succès."
|
163
|
+
|
164
|
+
end #/ build
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
# @return \Array<Node> Liste des actes du paradigme
|
169
|
+
#
|
170
|
+
def actes
|
171
|
+
@actes ||= begin
|
172
|
+
pfa.data.values.select do |node|
|
173
|
+
node.part?
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
# @return \String Chemin d'accès au fichier de l'image finale
|
180
|
+
def image_path
|
181
|
+
@image_path ||= File.expand_path(File.join('.','pfa.jpg'))
|
182
|
+
# @image_path ||= File.expand_path(File.join('.','pfa.img'))
|
183
|
+
end
|
184
|
+
|
185
|
+
# @private
|
186
|
+
|
187
|
+
# Calcule le coefficiant pixels qui permet de convertir un temps
|
188
|
+
# quelconque en pixels en fonction de la durée du film analysé.
|
189
|
+
# Produira la constant COEF_PIXELS
|
190
|
+
#
|
191
|
+
def calc_coefficient_pixels
|
192
|
+
(MagickPFA::PFA_WIDTH - MagickPFA::PFA_LEFT_MARGIN - MagickPFA::PFA_RIGHT_MARGIN).to_f / pfa.duration.to_i
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
end #/class ImgBuilder
|
197
|
+
end #/class RelativePFA
|
198
|
+
end #/module PFA
|
@@ -0,0 +1,188 @@
|
|
1
|
+
#
|
2
|
+
# Class PFA::NTime
|
3
|
+
# -------------------
|
4
|
+
# Pour la gestion des temps dans le paradigme de Field
|
5
|
+
# On ne passera plus par la class Time, trop compliquée
|
6
|
+
#
|
7
|
+
module PFA
|
8
|
+
class NTime
|
9
|
+
|
10
|
+
# \Integer Nombre de secondes pour ce temps
|
11
|
+
attr_reader :secondes
|
12
|
+
|
13
|
+
# \Integer Nombre de secondes du zéro
|
14
|
+
attr_reader :zero_offset
|
15
|
+
|
16
|
+
# On peut initialiser un NTime avec :
|
17
|
+
# - [Integer] Des secondes
|
18
|
+
# - [Time] Un temps
|
19
|
+
# - [String] Une horloge
|
20
|
+
# - [PFA::NTime] Une instance PFA::NTime (comme celle-ci)
|
21
|
+
#
|
22
|
+
# @param \Integer zero_offset Décalage du temps avec zéro
|
23
|
+
#
|
24
|
+
def initialize(foo, zero_offset = 0)
|
25
|
+
@zero_offset = zero_offset
|
26
|
+
case foo
|
27
|
+
when Integer then @secondes = foo
|
28
|
+
when Float then @secondes = foo.to_i
|
29
|
+
when PFA::NTime then @secondes = foo.to_i
|
30
|
+
when Time then @secondes = foo.to_i
|
31
|
+
when String then @secondes = PFA.h2s(foo)
|
32
|
+
else raise PFAFatalError.new(53, {value: "#{foo}", classe:"#{foo.class}"})
|
33
|
+
end
|
34
|
+
@secondes -= zero_offset
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def as_horloge
|
39
|
+
@to_horloge ||= PFA.s2h(secondes)
|
40
|
+
end
|
41
|
+
alias :to_horloge :as_horloge
|
42
|
+
|
43
|
+
def as_duree
|
44
|
+
@as_duree ||= PFA.s2h(secondes, **{as: :duree})
|
45
|
+
end
|
46
|
+
|
47
|
+
# -- Méthodes de décalage --
|
48
|
+
|
49
|
+
def calc_offset(abs_time)
|
50
|
+
offset_secondes = (abs_time.to_i - self.to_i).abs
|
51
|
+
@offset = self.class.new(offset_secondes)
|
52
|
+
@hasoffset = offset > 30
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [String] Une horloge qui indique le décalage avec
|
56
|
+
# la valeur idéale (seulement pour les noeuds relatifs) si ce
|
57
|
+
# décalage existe.
|
58
|
+
#
|
59
|
+
# @param abs_time [PFA::NTime] Le temps absolu
|
60
|
+
#
|
61
|
+
def as_horloge_with_offset(abs_time)
|
62
|
+
@as_horloge_with_offset ||= begin
|
63
|
+
if offset?
|
64
|
+
signe = self > abs_time ? '+' : '-'
|
65
|
+
"#{self.as_horloge} (#{signe}#{offset.as_duree})"
|
66
|
+
else
|
67
|
+
self.as_horloge
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return true s'il y a un décalage trop important avec le
|
73
|
+
# temps absolu
|
74
|
+
# @noter que cette méthode existe aussi pour le temps absolu
|
75
|
+
def offset?
|
76
|
+
@hasoffset === true
|
77
|
+
end
|
78
|
+
|
79
|
+
def offset_as_horloge(abs_time)
|
80
|
+
@offset_as_horloge ||= begin
|
81
|
+
if @hasoffset
|
82
|
+
signe = self > abs_time ? '+' : '-'
|
83
|
+
" (#{signe}#{offset.as_duree})"
|
84
|
+
else
|
85
|
+
" "
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def background_per_offset
|
91
|
+
@background_per_offset ||= begin
|
92
|
+
if offset > 120
|
93
|
+
'gray40' # offset trop grand
|
94
|
+
else
|
95
|
+
'transparent'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
def foreground_per_offset
|
100
|
+
@foreground_per_offset ||= begin
|
101
|
+
if offset < 60
|
102
|
+
'gray60'
|
103
|
+
elsif offset < 120
|
104
|
+
'gray20'
|
105
|
+
else
|
106
|
+
'white'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# [PFA::NTime] Décalage entre le temps absolu et le temps réel
|
112
|
+
def offset
|
113
|
+
@offset
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_i
|
117
|
+
@secondes
|
118
|
+
end
|
119
|
+
|
120
|
+
# Retourne la valeur en pixels pour le temps courant (ou la durée)
|
121
|
+
def to_px(pfa)
|
122
|
+
(self.to_i * pfa.img_builder.coef_pixels).to_i
|
123
|
+
end
|
124
|
+
|
125
|
+
# [PFA::NTime] Le temps relatif (à l'écran)
|
126
|
+
def relative
|
127
|
+
@relative ||= NTime.new(secondes + zero_offset, 0)
|
128
|
+
end
|
129
|
+
|
130
|
+
# --- Helpers Methods ---
|
131
|
+
|
132
|
+
# @retour [BashString] Le code pour écrire l'horloge dans une
|
133
|
+
# image avec ImageMagick pour le noeud +node+
|
134
|
+
#
|
135
|
+
# @param [PFA::RelativePFA::Node] node Le nœud de l'horloge
|
136
|
+
# @param [Hash] options
|
137
|
+
# Plus tard, pourra redéfinir :bg_color et :color
|
138
|
+
#
|
139
|
+
def as_img_horloge_code(node, **options)
|
140
|
+
for_real = options[:pfa_type] == :real
|
141
|
+
<<~CMD.strip
|
142
|
+
\\(
|
143
|
+
-background #{options[:bg_color]||'transparent'}
|
144
|
+
-stroke #{options[:color]||'gray20'}
|
145
|
+
-fill #{options[:color]||'gray20'}
|
146
|
+
-strokewidth 1
|
147
|
+
-pointsize #{MagickPFA::BASE_FONTSIZE * MagickPFA::HORLOGE_FONT_SIZES[node.type]}
|
148
|
+
-size #{surface}
|
149
|
+
-gravity #{options[:gravity]||'Center'}
|
150
|
+
label:"#{for_real ? self.as_horloge_with_offset(options[:abs_time]) : as_horloge}"
|
151
|
+
-extent #{surface}
|
152
|
+
\\)
|
153
|
+
-gravity northwest
|
154
|
+
-geometry +#{node.send(for_real ? :left : :abs_left) + 24}+#{node.send(for_real ? :top : :abs_top) + 8}
|
155
|
+
-composite
|
156
|
+
CMD
|
157
|
+
end
|
158
|
+
|
159
|
+
def surface
|
160
|
+
@surface ||= "#{MagickPFA::PFA_WIDTH/10}x50"
|
161
|
+
end
|
162
|
+
|
163
|
+
# --- Operation Methods ---
|
164
|
+
|
165
|
+
# Addition
|
166
|
+
#
|
167
|
+
# @param secondes \PFA::NTime ou \Integer
|
168
|
+
#
|
169
|
+
def +(secs)
|
170
|
+
secs = secs.to_i if secs.is_a?(PFA::NTime)
|
171
|
+
return PFA::NTime.new(secs + @secondes)
|
172
|
+
end
|
173
|
+
|
174
|
+
def -(secs)
|
175
|
+
secs = secs.to_i if secs.is_a?(PFA::NTime)
|
176
|
+
return PFA::NTime.new(@secondes - secs)
|
177
|
+
end
|
178
|
+
|
179
|
+
def <(nodetime)
|
180
|
+
@secondes < nodetime.to_i
|
181
|
+
end
|
182
|
+
|
183
|
+
def >(nodetime)
|
184
|
+
@secondes > nodetime.to_i
|
185
|
+
end
|
186
|
+
|
187
|
+
end #/class NTime
|
188
|
+
end #/module PFA
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#
|
2
|
+
# Pour ajouter des méthodes communes à RelativePFA::Node et
|
3
|
+
# RelativePFA::DataTime
|
4
|
+
#
|
5
|
+
module PFAElementModule
|
6
|
+
|
7
|
+
# @return true si c'est une partie (acte)
|
8
|
+
def part?
|
9
|
+
return abs_data[:type] == 'part'
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return true si c'est un élément imprimable (dans le tableau
|
13
|
+
# décrivant le PFA, à ne pas confondre avec le graphique)
|
14
|
+
def printable?
|
15
|
+
return abs_data[:printed] == true
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return true si c'est un élément à dessiner dans le graphique
|
19
|
+
# des deux PFA (idéal et réel)
|
20
|
+
def drawnable?
|
21
|
+
return abs_data[:drawn] == true
|
22
|
+
end
|
23
|
+
|
24
|
+
# Sera redéfini pour RelativePFA::Node, mais pas pour
|
25
|
+
#
|
26
|
+
def abs_data
|
27
|
+
{type: 'data_time', printed: false}
|
28
|
+
end
|
29
|
+
|
30
|
+
end #/module PFAElementModule
|
@@ -0,0 +1,191 @@
|
|
1
|
+
#
|
2
|
+
# PFA Relatif, donc celui étudié
|
3
|
+
#
|
4
|
+
module PFA
|
5
|
+
# Pour pouvoir faire :
|
6
|
+
# pfa = PFA.new
|
7
|
+
#
|
8
|
+
def self.new(data = nil)
|
9
|
+
RelativePFA.new(data)
|
10
|
+
end
|
11
|
+
|
12
|
+
# # Pour obtenir le PFA courant (au mépris de toute loi de Démeter…)
|
13
|
+
# #
|
14
|
+
# def self.current
|
15
|
+
# @@current
|
16
|
+
# end
|
17
|
+
# def self.current=(pfa)
|
18
|
+
# @@current = pfa
|
19
|
+
# end
|
20
|
+
|
21
|
+
class RelativePFA
|
22
|
+
|
23
|
+
# [Hash] Les données du Paradigme de Field Augmenté
|
24
|
+
attr_reader :data
|
25
|
+
|
26
|
+
# Instanciation du paradigme
|
27
|
+
#
|
28
|
+
# @param input_data [Hash|Nil] Données du paradigme fournies à l'instanciation
|
29
|
+
#
|
30
|
+
def initialize(input_data = nil)
|
31
|
+
@data = {}
|
32
|
+
#
|
33
|
+
# -- Traitement de toutes les données fournies --
|
34
|
+
#
|
35
|
+
input_data ||= {}
|
36
|
+
input_data.each { |k, v| add(k, v) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(method_name, *args, &block)
|
40
|
+
if data.key?(method_name)
|
41
|
+
data[method_name]
|
42
|
+
elsif AbsolutePFA.data[:nodes].key?(method_name)
|
43
|
+
data[method_name]
|
44
|
+
else
|
45
|
+
raise NoMethodError.new(method_name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Ajout d'un nœud dans le PFA
|
50
|
+
#
|
51
|
+
# On utilise pour le faire : pfa.add(key, value). Si c'est un
|
52
|
+
# nœud, la valeur contient {t: '<horloge>', d: "description"}
|
53
|
+
# La clé :t peut-être remplacée par :time ou :start_at
|
54
|
+
# La clé :d peut-être remplacée par :description
|
55
|
+
#
|
56
|
+
def add(key, value)
|
57
|
+
# puts "-> add(#{key.inspect}, #{value.inspect}::#{value.class})".orange
|
58
|
+
key = key.to_sym
|
59
|
+
if AbsolutePFA.data[:nodes].key?(key)
|
60
|
+
#
|
61
|
+
# Ajout d'un nœud
|
62
|
+
#
|
63
|
+
# @note
|
64
|
+
# Un noeud doit toujours être défini par une table contenant
|
65
|
+
# :t (ou :time) et :d (ou :description)
|
66
|
+
#
|
67
|
+
# La donnée doit être valide. On en profite aussi pour bien
|
68
|
+
# définir le temps.
|
69
|
+
#
|
70
|
+
value = value_valid?(value, key)
|
71
|
+
data.merge!(key => RelativePFA::Node.new(self, key, value))
|
72
|
+
|
73
|
+
elsif AbsolutePFA.data[:times].key?(key)
|
74
|
+
#
|
75
|
+
# Ajout d'une valeur temporelle
|
76
|
+
#
|
77
|
+
data.merge!(key => DataTime.new(self, key, value))
|
78
|
+
else
|
79
|
+
raise PFAFatalError.new(100, **{key: ":#{key}"})
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Test la pertinence de la définition de la clé +key+ et produit une
|
84
|
+
# erreur éclairante en cas de problème.
|
85
|
+
#
|
86
|
+
def value_valid?(value, key)
|
87
|
+
value.is_a?(Hash) || raise(PFAFatalError.new(219, **{key: key, classe: "#{value.class}"}))
|
88
|
+
value.merge!(t: value[:time]) if value.key?(:time)
|
89
|
+
value.merge!(d: value[:description]) if value.key?(:description)
|
90
|
+
value.key?(:t) || raise(PFAFatalError.new(221, **{noeud: key, classe: "#{value.class}"}))
|
91
|
+
value[:t] = PFA.time_from(value[:t])
|
92
|
+
value.key?(:d) || raise(PFAFatalError.new(222, **{noeud: key}))
|
93
|
+
return value
|
94
|
+
end
|
95
|
+
|
96
|
+
# @return true si les données relative du PFA sont valides
|
97
|
+
#
|
98
|
+
# Donc principalement qu'elles existent et qu'elles soient
|
99
|
+
# conformes aux attentes.
|
100
|
+
#
|
101
|
+
# Les données minimales pour construire le PFA sont :
|
102
|
+
# - le zéro
|
103
|
+
# - le temps de fin (end_time)
|
104
|
+
# - l'incident déclencheur
|
105
|
+
# - le pivot 1
|
106
|
+
# - le début du développement (developpement_part1)
|
107
|
+
# - le pivot 2
|
108
|
+
# - le début du dénouement (denouement)
|
109
|
+
# - le climax
|
110
|
+
#
|
111
|
+
def valid?
|
112
|
+
zero || raise(PFAFatalError.new(200))
|
113
|
+
end_time || raise(PFAFatalError.new(201))
|
114
|
+
exposition || raise(PFAFatalError.new(209))
|
115
|
+
incident_declencheur || raise(PFAFatalError.new(202))
|
116
|
+
pivot1 || raise(PFAFatalError.new(203))
|
117
|
+
developpement_part1 || raise(PFAFatalError.new(204))
|
118
|
+
developpement_part2 || raise(PFAFatalError.new(208))
|
119
|
+
pivot2 || raise(PFAFatalError.new(205))
|
120
|
+
denouement || raise(PFAFatalError.new(206))
|
121
|
+
climax || raise(PFAFatalError.new(207))
|
122
|
+
|
123
|
+
# --- Vérification de la validité des temps ---
|
124
|
+
#
|
125
|
+
incident_declencheur.start_at > zero || raise_time_error('zero','incident_declencheur')
|
126
|
+
pivot1.after?(incident_declencheur) || raise_time_error('incident_declencheur','pivot1')
|
127
|
+
developpement_part1.after?(pivot1) || raise_time_error('pivot1', 'developpement_part1')
|
128
|
+
if cle_de_voute
|
129
|
+
cle_de_voute.after?(developpement_part1) || raise_time_error('developpement_part1','cle_de_voute')
|
130
|
+
end
|
131
|
+
pivot2.after?(pivot1) || raise_time_error('pivot1', 'pivot2')
|
132
|
+
if developpement_part2
|
133
|
+
if cle_de_voute
|
134
|
+
developpement_part2.after?(cle_de_voute) || raise_time_error('cle_de_voute', 'developpement_part2')
|
135
|
+
end
|
136
|
+
pivot2.after?(developpement_part2) || raise_time_error('developpement_part2', 'pivot2')
|
137
|
+
end
|
138
|
+
denouement.after?(pivot2) || raise_time_error('pivot2','denouement')
|
139
|
+
climax.after?(denouement) || raise_time_error('denouement','climax')
|
140
|
+
data[:end_time].time > climax.start_at || raise_time_error('end_time','climax', end_time, climax)
|
141
|
+
end
|
142
|
+
|
143
|
+
def raise_time_error(key_before, key_after)
|
144
|
+
h_before = self.send(key_before.to_sym)
|
145
|
+
h_after = self.send(key_after.to_sym)
|
146
|
+
h_before = PFA.t2h(h_before) if h_before.is_a?(Time)
|
147
|
+
h_after = PFA.t2h(h_after) if h_after.is_a?(Time)
|
148
|
+
h_before = h_before.horloge if h_before.is_a?(Node)
|
149
|
+
h_after = h_after.horloge if h_after.is_a?(Node)
|
150
|
+
raise PFAFatalError.new(220, **{
|
151
|
+
key_before: key_before, h_before: h_before,
|
152
|
+
key_after: key_after, h_after: h_after
|
153
|
+
})
|
154
|
+
end
|
155
|
+
|
156
|
+
# --- Volatile Data ---
|
157
|
+
|
158
|
+
def zero ; data[:zero].time unless data[:zero].nil? end
|
159
|
+
def end_time ; data[:end_time].time unless data[:end_time].nil? end
|
160
|
+
def duree
|
161
|
+
@duree ||= PFA::NTime.new(end_time, zero.to_i)
|
162
|
+
end
|
163
|
+
alias :duration :duree
|
164
|
+
|
165
|
+
# Définitions -raccourcis-
|
166
|
+
def zero=(value) ; add(:zero, value) end
|
167
|
+
def end_time=(value) ; add(:end_time, value) end
|
168
|
+
|
169
|
+
|
170
|
+
# --- Helper Methods ---
|
171
|
+
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
# --- Output Methods ---
|
176
|
+
|
177
|
+
def to_html(**params)
|
178
|
+
puts "Je dois apprendre à sortir en HTML".orange
|
179
|
+
end
|
180
|
+
|
181
|
+
def to_img(**params)
|
182
|
+
params.key?(:as) || params.merge!(as: :real_book)
|
183
|
+
img_builder.build(**params)
|
184
|
+
end
|
185
|
+
|
186
|
+
def img_builder
|
187
|
+
@img_builder ||= ImgBuilder.new(self)
|
188
|
+
end
|
189
|
+
|
190
|
+
end #/ class RelativePFA
|
191
|
+
end #/ module PFA
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'pfa_element_module'
|
2
|
+
module PFA
|
3
|
+
class RelativePFA
|
4
|
+
class DataTime
|
5
|
+
|
6
|
+
include PFAElementModule
|
7
|
+
|
8
|
+
attr_reader :pfa, :key
|
9
|
+
|
10
|
+
def initialize(pfa, key, value = nil)
|
11
|
+
@pfa = pfa
|
12
|
+
@key = key
|
13
|
+
@raw_value = value
|
14
|
+
end
|
15
|
+
|
16
|
+
def time
|
17
|
+
@time ||= PFA::NTime.new(@raw_value, 0)
|
18
|
+
end
|
19
|
+
alias :start_at :time
|
20
|
+
|
21
|
+
# Pour la compatibilité quand on boucle sur tous les éléments
|
22
|
+
# des données du paradigme relatif
|
23
|
+
def type; nil end
|
24
|
+
|
25
|
+
end #/class DataTime
|
26
|
+
end #/class RelativePFA
|
27
|
+
end #/module PFA
|