@@ -20,19 +20,9 @@ def url_from_path(path)
2020 "#{ root_url . chomp ( '/' ) } #{ path } "
2121 end
2222
23- def set_videos_and_blocks_and_callouts
23+ def set_videos_and_callouts
2424 @autoplay_video_info = select_and_track_autoplay_video
2525 @callouts = select_and_remember_callouts ( params [ :show_callouts ] )
26-
27- if @level . is_a? Blockly
28- @toolbox_blocks ||=
29- @level . try ( :project_template_level ) . try ( :toolbox_blocks ) ||
30- @level . toolbox_blocks
31-
32- @start_blocks ||=
33- @level . try ( :project_template_level ) . try ( :start_blocks ) ||
34- @level . start_blocks
35- end
3626 end
3727
3828 def select_and_track_autoplay_video
@@ -137,23 +127,25 @@ def boolean_string_false
137127 "false"
138128 end
139129
140- # Code for generating the blockly options hash
141- def blockly_options ( local_assigns = { } )
130+ # Generate a level-specific blockly options hash
131+ def blockly_level_options ( level )
142132 # Use values from properties json when available (use String keys instead of Symbols for consistency)
143- level = @level . properties . dup || { }
133+ level_prop = level . properties . dup || { }
134+
135+ extra_options = level . embed == 'true' ? { embed : true , hide_source : true , no_padding : true , show_finish : true } : { }
144136
145137 # Set some specific values
146- level [ 'puzzle_number' ] = @script_level ? @script_level . position : 1
147- level [ 'stage_total' ] = @script_level ? @script_level . stage_total : 1
148- if @level . is_a? ( Maze ) && @level . step_mode
149- @level . step_mode = blockly_value ( @level . step_mode )
150- level [ 'step' ] = @level . step_mode == 1 || @level . step_mode == 2
151- level [ 'stepOnly' ] = @level . step_mode == 2
138+
139+ if level . is_a? Blockly
140+ level_prop [ 'start_blocks' ] = level . try ( :project_template_level ) . try ( :start_blocks ) || level . start_blocks
141+ level_prop [ 'toolbox_blocks' ] = level . try ( :project_template_level ) . try ( :toolbox_blocks ) || level . toolbox_blocks
152142 end
153143
154- # Pass blockly the edit mode: "<start|toolbox|required>_blocks"
155- level [ 'edit_blocks' ] = params [ :type ]
156- level [ 'edit_blocks_success' ] = t ( 'builder.success' )
144+ if level . is_a? ( Maze ) && level . step_mode
145+ step_mode = blockly_value ( level . step_mode )
146+ level_prop [ 'step' ] = step_mode == 1 || step_mode == 2
147+ level_prop [ 'stepOnly' ] = step_mode == 2
148+ end
157149
158150 # Map Dashboard-style names to Blockly-style names in level object.
159151 # Dashboard underscore_names mapped to Blockly lowerCamelCase, or explicit 'Dashboard:Blockly'
@@ -220,83 +212,119 @@ def blockly_options(local_assigns={})
220212 is_project_level
221213 failure_message_override
222214 ) . map { |x | x . include? ( ':' ) ? x . split ( ':' ) : [ x , x . camelize ( :lower ) ] } ]
223- . each do |dashboard , blockly |
224- # Select first valid value from 1. local_assigns, 2. property of @level object, 3. named instance variable, 4. properties json
215+ . each do |dashboard , blockly |
216+ # Select value from extra options, or properties json
225217 # Don't override existing valid (non-nil/empty) values
226- property = local_assigns [ dashboard . to_sym ] . presence ||
227- @level [ dashboard ] . presence ||
228- instance_variable_get ( "@#{ dashboard } " ) . presence ||
229- level [ dashboard ] . presence
230- value = blockly_value ( level [ blockly ] || property )
231- level [ blockly ] = value unless value . nil? # make sure we convert false
218+ property = extra_options [ dashboard ] . presence ||
219+ level_prop [ dashboard ] . presence
220+ value = blockly_value ( level_prop [ blockly ] || property )
221+ level_prop [ blockly ] = value unless value . nil? # make sure we convert false
232222 end
233223
234- level [ 'images' ] = JSON . parse ( level [ 'images' ] ) if level [ 'images' ] . present?
224+ level_prop [ 'images' ] = JSON . parse ( level_prop [ 'images' ] ) if level_prop [ 'images' ] . present?
235225
236226 # Blockly requires startDirection as an integer not a string
237- level [ 'startDirection' ] = level [ 'startDirection' ] . to_i if level [ 'startDirection' ] . present?
238- level [ 'sliderSpeed' ] = level [ 'sliderSpeed' ] . to_f if level [ 'sliderSpeed' ]
239- level [ 'scale' ] = { 'stepSpeed' => @level . properties [ 'step_speed' ] . to_i } if @level . properties [ 'step_speed' ] . present?
227+ level_prop [ 'startDirection' ] = level_prop [ 'startDirection' ] . to_i if level_prop [ 'startDirection' ] . present?
228+ level_prop [ 'sliderSpeed' ] = level_prop [ 'sliderSpeed' ] . to_f if level_prop [ 'sliderSpeed' ]
229+ level_prop [ 'scale' ] = { 'stepSpeed' => level_prop [ 'step_speed' ] . to_i } if level_prop [ 'step_speed' ] . present?
240230
241231 # Blockly requires these fields to be objects not strings
242232 %w( map initialDirt finalDirt goal soft_buttons ) . each do |x |
243- level [ x ] = JSON . parse ( level [ x ] ) if level [ x ] . is_a? String
233+ level_prop [ x ] = JSON . parse ( level_prop [ x ] ) if level_prop [ x ] . is_a? String
244234 end
245235
246236 # Blockly expects fn_successCondition and fn_failureCondition to be inside a 'goals' object
247- if level [ 'fn_successCondition' ] || level [ 'fn_failureCondition' ]
248- level [ 'goal' ] = { fn_successCondition : level [ 'fn_successCondition' ] , fn_failureCondition : level [ 'fn_failureCondition' ] }
249- level . delete ( 'fn_successCondition' )
250- level . delete ( 'fn_failureCondition' )
237+ if level_prop [ 'fn_successCondition' ] || level_prop [ 'fn_failureCondition' ]
238+ level_prop [ 'goal' ] = { fn_successCondition : level_prop [ 'fn_successCondition' ] , fn_failureCondition : level_prop [ 'fn_failureCondition' ] }
239+ level_prop . delete ( 'fn_successCondition' )
240+ level_prop . delete ( 'fn_failureCondition' )
241+ end
242+
243+ app_options = { }
244+
245+ app_options [ :levelGameName ] = level . game . name if level . game
246+ app_options [ :skinId ] = level . skin if level . is_a? ( Blockly )
247+
248+ # Set some values that Blockly expects on the root of its options string
249+ app_options . merge! ( {
250+ baseUrl : "#{ ActionController ::Base . asset_host } /blockly/" ,
251+ app : level . game . try ( :app ) ,
252+ levelId : level . level_num ,
253+ level : level_prop ,
254+ cacheBust : blockly_cache_bust ,
255+ droplet : level . game . try ( :uses_droplet? ) ,
256+ pretty : Rails . configuration . pretty_apps ? '' : '.min' ,
257+ } )
258+
259+ # Move these values up to the root
260+ %w( hideSource share noPadding embed ) . each do |key |
261+ app_options [ key . to_sym ] = level_prop [ key ]
262+ level_prop . delete key
251263 end
252264
253- #Fetch localized strings
254- if @level . level_num_custom?
255- loc_val = data_t ( "instructions" , "#{ @level . name } _instruction" )
265+ app_options
266+ end
267+
268+ # Code for generating the blockly options hash
269+ def blockly_options
270+
271+ ## Level-dependent options
272+ l = @level
273+ app_options = Rails . cache . fetch ( "#{ l . cache_key } /blockly_level_options" ) do
274+ blockly_level_options ( l )
275+ end
276+ level_options = app_options [ :level ]
277+
278+ ## Locale-dependent option
279+ # Fetch localized strings
280+ if l . level_num_custom?
281+ loc_val = data_t ( "instructions" , "#{ l . name } _instruction" )
256282 unless I18n . locale . to_s == 'en-us' || loc_val . nil?
257- level [ 'instructions' ] = loc_val
283+ level_options [ 'instructions' ] = loc_val
258284 end
259285 else
260286 %w( instructions ) . each do |label |
261- val = [ @level . game . app , @level . game . name ] . map { |name |
262- data_t ( "level.#{ label } " , "#{ name } _#{ @level . level_num } " )
287+ val = [ l . game . app , l . game . name ] . map { |name |
288+ data_t ( "level.#{ label } " , "#{ name } _#{ l . level_num } " )
263289 } . compact . first
264- level [ label ] ||= val unless val . nil?
290+ level_options [ label ] ||= val unless val . nil?
265291 end
266292 end
267293
268- # Set some values that Blockly expects on the root of its options string
269- app_options = {
270- baseUrl : "#{ ActionController ::Base . asset_host } /blockly/" ,
271- app : @game . try ( :app ) ,
272- levelId : @level . level_num ,
273- level : level ,
274- callouts : @callouts ,
275- cacheBust : blockly_cache_bust ,
276- autoplayVideo : @autoplay_video_info ,
277- report : {
278- fallback_response : @fallback_response ,
279- callback : @callback ,
280- } ,
281- droplet : @game . try ( :uses_droplet? ) ,
282- pretty : Rails . configuration . pretty_apps ? '' : '.min' ,
283- applabUserId : @applab_user_id ,
284- }
285- app_options [ :scriptId ] = @script . id if @script
286- app_options [ :levelGameName ] = @level . game . name if @level . game
287- app_options [ :skinId ] = @level . skin if @level . is_a? ( Blockly )
294+ ## Script-dependent option
295+ script = @script
296+ app_options [ :scriptId ] = script . id if script
297+
298+ ## ScriptLevel-dependent option
299+ script_level = @script_level
300+ level_options [ 'puzzle_number' ] = script_level ? script_level . position : 1
301+ level_options [ 'stage_total' ] = script_level ? script_level . stage_total : 1
302+
303+ ## LevelSource-dependent options
288304 app_options [ :level_source_id ] = @level_source . id if @level_source
289- app_options [ :sendToPhone ] = request . location . try ( :country_code ) == 'US' ||
290- ( !Rails . env . production? && request . location . try ( :country_code ) == 'RD' ) if request
291305 app_options [ :send_to_phone_url ] = @phone_share_url if @phone_share_url
292- app_options [ :disableSocialShare ] = true if ( @current_user && @current_user . under_13? ) || @embed
293306
294- # Move these values up to the root
295- %w( hideSource share noPadding embed ) . each do |key |
296- app_options [ key . to_sym ] = level [ key ]
297- level . delete key
307+ ## Edit blocks-dependent options
308+ if @edit_blocks
309+ # Pass blockly the edit mode: "<start|toolbox|required>_blocks"
310+ level_options [ 'edit_blocks' ] = @edit_blocks
311+ level_options [ 'edit_blocks_success' ] = t ( 'builder.success' )
298312 end
299313
314+ ## User/session-dependent options
315+ app_options [ :callouts ] = @callouts
316+ app_options [ :autoplayVideo ] = @autoplay_video_info
317+ app_options [ :disableSocialShare ] = true if ( @current_user && @current_user . under_13? ) || @embed
318+ app_options [ :applabUserId ] = @applab_user_id
319+ app_options [ :report ] = {
320+ fallback_response : @fallback_response ,
321+ callback : @callback ,
322+ }
323+
324+ ## Request-dependent option
325+ app_options [ :sendToPhone ] = request . location . try ( :country_code ) == 'US' ||
326+ ( !Rails . env . production? && request . location . try ( :country_code ) == 'RD' ) if request
327+
300328 app_options
301329 end
302330
0 commit comments