pfa 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|