blockly 7.20211209.2 → 8.0.0
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.
- package/blockly.d.ts +18963 -18432
- package/blockly.min.js +852 -844
- package/blockly_compressed.js +669 -664
- package/blockly_compressed.js.map +1 -1
- package/blocks/blocks.js +47 -0
- package/blocks/colour.js +13 -3
- package/blocks/lists.js +22 -13
- package/blocks/logic.js +13 -3
- package/blocks/loops.js +24 -11
- package/blocks/math.js +12 -3
- package/blocks/procedures.js +41 -27
- package/blocks/text.js +22 -13
- package/blocks/variables.js +14 -3
- package/blocks/variables_dynamic.js +13 -3
- package/blocks_compressed.js +146 -141
- package/blocks_compressed.js.map +1 -1
- package/core/block.js +1869 -1814
- package/core/block_drag_surface.js +201 -200
- package/core/block_dragger.js +377 -373
- package/core/block_svg.js +1593 -1479
- package/core/blockly.js +8 -22
- package/core/blocks.js +9 -2
- package/core/browser_events.js +22 -5
- package/core/bubble.js +841 -797
- package/core/bubble_dragger.js +213 -206
- package/core/bump_objects.js +2 -2
- package/core/clipboard.js +9 -9
- package/core/comment.js +353 -332
- package/core/common.js +46 -17
- package/core/component_manager.js +181 -174
- package/core/config.js +87 -0
- package/core/connection.js +595 -584
- package/core/connection_checker.js +242 -244
- package/core/connection_db.js +235 -230
- package/core/contextmenu.js +9 -6
- package/core/contextmenu_items.js +1 -2
- package/core/contextmenu_registry.js +93 -89
- package/core/css.js +474 -474
- package/core/delete_area.js +45 -42
- package/core/drag_target.js +57 -56
- package/core/dropdowndiv.js +153 -163
- package/core/events/events.js +2 -2
- package/core/events/events_abstract.js +89 -77
- package/core/events/events_block_base.js +37 -36
- package/core/events/events_block_change.js +130 -124
- package/core/events/events_block_create.js +73 -71
- package/core/events/events_block_delete.js +84 -82
- package/core/events/events_block_drag.js +50 -49
- package/core/events/events_block_move.js +147 -140
- package/core/events/events_bubble_open.js +51 -50
- package/core/events/events_click.js +48 -44
- package/core/events/events_comment_base.js +72 -69
- package/core/events/events_comment_change.js +63 -61
- package/core/events/events_comment_create.js +44 -42
- package/core/events/events_comment_delete.js +42 -40
- package/core/events/events_comment_move.js +106 -104
- package/core/events/events_marker_move.js +65 -64
- package/core/events/events_selected.js +46 -45
- package/core/events/events_theme_change.js +36 -35
- package/core/events/events_toolbox_item_select.js +46 -45
- package/core/events/events_trashcan_open.js +37 -36
- package/core/events/events_ui.js +47 -46
- package/core/events/events_ui_base.js +30 -29
- package/core/events/events_var_base.js +37 -36
- package/core/events/events_var_create.js +50 -48
- package/core/events/events_var_delete.js +50 -48
- package/core/events/events_var_rename.js +51 -49
- package/core/events/events_viewport.js +66 -65
- package/core/events/utils.js +29 -14
- package/core/events/workspace_events.js +49 -55
- package/core/extensions.js +4 -3
- package/core/field.js +1061 -997
- package/core/field_angle.js +462 -442
- package/core/field_checkbox.js +194 -182
- package/core/field_colour.js +519 -505
- package/core/field_dropdown.js +617 -598
- package/core/field_image.js +229 -220
- package/core/field_label.js +102 -91
- package/core/field_label_serializable.js +42 -41
- package/core/field_multilineinput.js +372 -358
- package/core/field_number.js +272 -253
- package/core/field_textinput.js +499 -467
- package/core/field_variable.js +458 -420
- package/core/flyout_base.js +1005 -952
- package/core/flyout_button.js +277 -260
- package/core/flyout_horizontal.js +304 -302
- package/core/flyout_metrics_manager.js +64 -64
- package/core/flyout_vertical.js +306 -300
- package/core/generator.js +459 -446
- package/core/gesture.js +829 -813
- package/core/grid.js +166 -163
- package/core/icon.js +168 -159
- package/core/inject.js +7 -5
- package/core/input.js +257 -248
- package/core/insertion_marker_manager.js +655 -624
- package/core/internal_constants.js +0 -129
- package/core/keyboard_nav/ast_node.js +605 -596
- package/core/keyboard_nav/basic_cursor.js +166 -165
- package/core/keyboard_nav/cursor.js +99 -97
- package/core/keyboard_nav/marker.js +83 -79
- package/core/keyboard_nav/tab_navigate_cursor.js +18 -23
- package/core/marker_manager.js +153 -141
- package/core/menu.js +377 -372
- package/core/menuitem.js +223 -217
- package/core/metrics_manager.js +403 -390
- package/core/mutator.js +468 -437
- package/core/names.js +229 -188
- package/core/options.js +290 -284
- package/core/procedures.js +29 -17
- package/core/registry.js +19 -16
- package/core/rendered_connection.js +482 -463
- package/core/renderers/common/block_rendering.js +9 -3
- package/core/renderers/common/constants.js +1119 -1112
- package/core/renderers/common/debug.js +14 -0
- package/core/renderers/common/debugger.js +338 -316
- package/core/renderers/common/drawer.js +380 -370
- package/core/renderers/common/i_path_object.js +2 -2
- package/core/renderers/common/info.js +626 -618
- package/core/renderers/common/marker_svg.js +579 -541
- package/core/renderers/common/path_object.js +203 -200
- package/core/renderers/common/renderer.js +220 -218
- package/core/renderers/geras/constants.js +36 -36
- package/core/renderers/geras/drawer.js +155 -147
- package/core/renderers/geras/highlight_constants.js +244 -238
- package/core/renderers/geras/highlighter.js +231 -179
- package/core/renderers/geras/info.js +392 -369
- package/core/renderers/geras/measurables/inline_input.js +25 -19
- package/core/renderers/geras/measurables/statement_input.js +23 -17
- package/core/renderers/geras/path_object.js +106 -121
- package/core/renderers/geras/renderer.js +96 -98
- package/core/renderers/measurables/base.js +30 -18
- package/core/renderers/measurables/bottom_row.js +83 -80
- package/core/renderers/measurables/connection.js +22 -15
- package/core/renderers/measurables/external_value_input.js +35 -22
- package/core/renderers/measurables/field.js +35 -20
- package/core/renderers/measurables/hat.js +18 -13
- package/core/renderers/measurables/icon.js +24 -17
- package/core/renderers/measurables/in_row_spacer.js +15 -13
- package/core/renderers/measurables/inline_input.js +43 -33
- package/core/renderers/measurables/input_connection.js +41 -28
- package/core/renderers/measurables/input_row.js +50 -44
- package/core/renderers/measurables/jagged_edge.js +14 -12
- package/core/renderers/measurables/next_connection.js +16 -14
- package/core/renderers/measurables/output_connection.js +26 -20
- package/core/renderers/measurables/previous_connection.js +16 -15
- package/core/renderers/measurables/round_corner.js +20 -18
- package/core/renderers/measurables/row.js +184 -168
- package/core/renderers/measurables/spacer_row.js +38 -23
- package/core/renderers/measurables/square_corner.js +18 -16
- package/core/renderers/measurables/statement_input.js +23 -20
- package/core/renderers/measurables/top_row.js +88 -85
- package/core/renderers/minimalist/constants.js +8 -7
- package/core/renderers/minimalist/drawer.js +11 -10
- package/core/renderers/minimalist/info.js +18 -18
- package/core/renderers/minimalist/renderer.js +40 -39
- package/core/renderers/thrasos/info.js +258 -248
- package/core/renderers/thrasos/renderer.js +20 -20
- package/core/renderers/zelos/constants.js +898 -873
- package/core/renderers/zelos/drawer.js +186 -169
- package/core/renderers/zelos/info.js +502 -479
- package/core/renderers/zelos/marker_svg.js +129 -115
- package/core/renderers/zelos/measurables/bottom_row.js +31 -30
- package/core/renderers/zelos/measurables/inputs.js +22 -21
- package/core/renderers/zelos/measurables/row_elements.js +14 -13
- package/core/renderers/zelos/measurables/top_row.js +34 -33
- package/core/renderers/zelos/path_object.js +181 -180
- package/core/renderers/zelos/renderer.js +91 -92
- package/core/scrollbar.js +759 -713
- package/core/scrollbar_pair.js +250 -245
- package/core/serialization/blocks.js +19 -9
- package/core/serialization/workspaces.js +3 -2
- package/core/shortcut_registry.js +286 -277
- package/core/sprites.js +31 -0
- package/core/theme.js +135 -141
- package/core/theme_manager.js +147 -143
- package/core/toolbox/category.js +602 -576
- package/core/toolbox/collapsible_category.js +226 -227
- package/core/toolbox/separator.js +70 -61
- package/core/toolbox/toolbox.js +934 -927
- package/core/toolbox/toolbox_item.js +115 -99
- package/core/tooltip.js +108 -35
- package/core/touch.js +8 -3
- package/core/touch_gesture.js +254 -251
- package/core/trashcan.js +606 -595
- package/core/utils/coordinate.js +97 -95
- package/core/utils/dom.js +2 -2
- package/core/utils/global.js +2 -0
- package/core/utils/rect.js +41 -37
- package/core/utils/sentinel.js +25 -0
- package/core/utils/size.js +30 -27
- package/core/utils/svg.js +18 -16
- package/core/variable_map.js +325 -341
- package/core/variable_model.js +55 -54
- package/core/variables.js +9 -2
- package/core/variables_dynamic.js +3 -1
- package/core/warning.js +126 -120
- package/core/widgetdiv.js +4 -4
- package/core/workspace.js +685 -664
- package/core/workspace_audio.js +124 -118
- package/core/workspace_comment.js +308 -298
- package/core/workspace_comment_svg.js +1029 -951
- package/core/workspace_drag_surface_svg.js +147 -140
- package/core/workspace_dragger.js +70 -71
- package/core/workspace_svg.js +2322 -2297
- package/core/xml.js +30 -20
- package/core/zoom_controls.js +431 -439
- package/dart_compressed.js +40 -43
- package/dart_compressed.js.map +1 -1
- package/generators/dart/colour.js +56 -64
- package/generators/dart/lists.js +61 -50
- package/generators/dart/math.js +160 -148
- package/generators/dart/text.js +83 -61
- package/generators/javascript/colour.js +37 -34
- package/generators/javascript/lists.js +50 -43
- package/generators/javascript/math.js +123 -139
- package/generators/javascript/text.js +67 -81
- package/generators/lua/colour.js +25 -23
- package/generators/lua/lists.js +97 -69
- package/generators/lua/logic.js +1 -2
- package/generators/lua/math.js +182 -144
- package/generators/lua/text.js +116 -99
- package/generators/php/colour.js +38 -32
- package/generators/php/lists.js +109 -89
- package/generators/php/math.js +90 -81
- package/generators/php/text.js +63 -61
- package/generators/python/colour.js +18 -18
- package/generators/python/lists.js +38 -30
- package/generators/python/loops.js +12 -8
- package/generators/python/math.js +104 -106
- package/generators/python/text.js +34 -30
- package/javascript_compressed.js +37 -39
- package/javascript_compressed.js.map +1 -1
- package/lua_compressed.js +39 -42
- package/lua_compressed.js.map +1 -1
- package/msg/az.js +2 -2
- package/msg/be.js +4 -4
- package/msg/cs.js +15 -15
- package/msg/de.js +1 -1
- package/msg/diq.js +1 -1
- package/msg/eo.js +1 -1
- package/msg/es.js +1 -1
- package/msg/fa.js +1 -1
- package/msg/fr.js +4 -4
- package/msg/he.js +1 -1
- package/msg/hr.js +2 -2
- package/msg/hy.js +2 -2
- package/msg/id.js +12 -12
- package/msg/inh.js +14 -14
- package/msg/ja.js +7 -7
- package/msg/lv.js +29 -29
- package/msg/pa.js +3 -3
- package/msg/smn.js +436 -0
- package/msg/te.js +1 -1
- package/msg/yue.js +1 -1
- package/msg/zh-hans.js +3 -3
- package/msg/zh-hant.js +3 -3
- package/package.json +7 -6
- package/php_compressed.js +38 -42
- package/php_compressed.js.map +1 -1
- package/python_compressed.js +26 -25
- package/python_compressed.js.map +1 -1
- package/blocks/all.js +0 -23
package/generators/php/lists.js
CHANGED
|
@@ -44,11 +44,15 @@ PHP['lists_create_with'] = function(block) {
|
|
|
44
44
|
|
|
45
45
|
PHP['lists_repeat'] = function(block) {
|
|
46
46
|
// Create a list with one element repeated.
|
|
47
|
-
const functionName = PHP.provideFunction_('lists_repeat',
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
const functionName = PHP.provideFunction_('lists_repeat', `
|
|
48
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($value, $count) {
|
|
49
|
+
$array = array();
|
|
50
|
+
for ($index = 0; $index < $count; $index++) {
|
|
51
|
+
$array[] = $value;
|
|
52
|
+
}
|
|
53
|
+
return $array;
|
|
54
|
+
}
|
|
55
|
+
`);
|
|
52
56
|
const element = PHP.valueToCode(block, 'ITEM', PHP.ORDER_NONE) || 'null';
|
|
53
57
|
const repeatCount = PHP.valueToCode(block, 'NUM', PHP.ORDER_NONE) || '0';
|
|
54
58
|
const code = functionName + '(' + element + ', ' + repeatCount + ')';
|
|
@@ -57,12 +61,16 @@ PHP['lists_repeat'] = function(block) {
|
|
|
57
61
|
|
|
58
62
|
PHP['lists_length'] = function(block) {
|
|
59
63
|
// String or array length.
|
|
60
|
-
const functionName = PHP.provideFunction_('length',
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
const functionName = PHP.provideFunction_('length', `
|
|
65
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($value) {
|
|
66
|
+
if (is_string($value)) {
|
|
67
|
+
return strlen($value);
|
|
68
|
+
} else {
|
|
69
|
+
return count($value);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
`);
|
|
73
|
+
const list = PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || "''";
|
|
66
74
|
return [functionName + '(' + list + ')', PHP.ORDER_FUNCTION_CALL];
|
|
67
75
|
};
|
|
68
76
|
|
|
@@ -75,7 +83,7 @@ PHP['lists_isEmpty'] = function(block) {
|
|
|
75
83
|
|
|
76
84
|
PHP['lists_indexOf'] = function(block) {
|
|
77
85
|
// Find an item in the list.
|
|
78
|
-
const argument0 = PHP.valueToCode(block, 'FIND', PHP.ORDER_NONE) || '
|
|
86
|
+
const argument0 = PHP.valueToCode(block, 'FIND', PHP.ORDER_NONE) || "''";
|
|
79
87
|
const argument1 = PHP.valueToCode(block, 'VALUE', PHP.ORDER_MEMBER) || '[]';
|
|
80
88
|
let errorIndex = ' -1';
|
|
81
89
|
let indexAdjustment = '';
|
|
@@ -86,23 +94,25 @@ PHP['lists_indexOf'] = function(block) {
|
|
|
86
94
|
let functionName;
|
|
87
95
|
if (block.getFieldValue('END') === 'FIRST') {
|
|
88
96
|
// indexOf
|
|
89
|
-
functionName = PHP.provideFunction_('indexOf',
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
functionName = PHP.provideFunction_('indexOf', `
|
|
98
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($haystack, $needle) {
|
|
99
|
+
for ($index = 0; $index < count($haystack); $index++) {
|
|
100
|
+
if ($haystack[$index] == $needle) return $index${indexAdjustment};
|
|
101
|
+
}
|
|
102
|
+
return ${errorIndex};
|
|
103
|
+
}
|
|
104
|
+
`);
|
|
96
105
|
} else {
|
|
97
106
|
// lastIndexOf
|
|
98
|
-
functionName = PHP.provideFunction_('lastIndexOf',
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
functionName = PHP.provideFunction_('lastIndexOf', `
|
|
108
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($haystack, $needle) {
|
|
109
|
+
$last = ${errorIndex};
|
|
110
|
+
for ($index = 0; $index < count($haystack); $index++) {
|
|
111
|
+
if ($haystack[$index] == $needle) $last = $index${indexAdjustment};
|
|
112
|
+
}
|
|
113
|
+
return $last;
|
|
114
|
+
}
|
|
115
|
+
`);
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
const code = functionName + '(' + argument1 + ', ' + argument0 + ')';
|
|
@@ -191,26 +201,30 @@ PHP['lists_getIndex'] = function(block) {
|
|
|
191
201
|
case 'RANDOM': {
|
|
192
202
|
const list = PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()';
|
|
193
203
|
if (mode === 'GET') {
|
|
194
|
-
const functionName = PHP.provideFunction_('lists_get_random_item',
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
204
|
+
const functionName = PHP.provideFunction_('lists_get_random_item', `
|
|
205
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($list) {
|
|
206
|
+
return $list[rand(0,count($list)-1)];
|
|
207
|
+
}
|
|
208
|
+
`);
|
|
198
209
|
const code = functionName + '(' + list + ')';
|
|
199
210
|
return [code, PHP.ORDER_FUNCTION_CALL];
|
|
200
211
|
} else if (mode === 'GET_REMOVE') {
|
|
201
212
|
const functionName =
|
|
202
|
-
PHP.provideFunction_('lists_get_remove_random_item',
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
213
|
+
PHP.provideFunction_('lists_get_remove_random_item', `
|
|
214
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list) {
|
|
215
|
+
$x = rand(0,count($list)-1);
|
|
216
|
+
unset($list[$x]);
|
|
217
|
+
return array_values($list);
|
|
218
|
+
}
|
|
219
|
+
`);
|
|
207
220
|
const code = functionName + '(' + list + ')';
|
|
208
221
|
return [code, PHP.ORDER_FUNCTION_CALL];
|
|
209
222
|
} else if (mode === 'REMOVE') {
|
|
210
|
-
const functionName = PHP.provideFunction_('lists_remove_random_item',
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
223
|
+
const functionName = PHP.provideFunction_('lists_remove_random_item', `
|
|
224
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list) {
|
|
225
|
+
unset($list[rand(0,count($list)-1)]);
|
|
226
|
+
}
|
|
227
|
+
`);
|
|
214
228
|
return functionName + '(' + list + ');\n';
|
|
215
229
|
}
|
|
216
230
|
break;
|
|
@@ -252,10 +266,11 @@ PHP['lists_setIndex'] = function(block) {
|
|
|
252
266
|
case 'LAST': {
|
|
253
267
|
const list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()';
|
|
254
268
|
if (mode === 'SET') {
|
|
255
|
-
const functionName = PHP.provideFunction_('lists_set_last_item',
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
269
|
+
const functionName = PHP.provideFunction_('lists_set_last_item', `
|
|
270
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list, $value) {
|
|
271
|
+
$list[count($list) - 1] = $value;
|
|
272
|
+
}
|
|
273
|
+
`);
|
|
259
274
|
return functionName + '(' + list + ', ' + value + ');\n';
|
|
260
275
|
} else if (mode === 'INSERT') {
|
|
261
276
|
return 'array_push(' + list + ', ' + value + ');\n';
|
|
@@ -279,18 +294,18 @@ PHP['lists_setIndex'] = function(block) {
|
|
|
279
294
|
const list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()';
|
|
280
295
|
const at = PHP.getAdjusted(block, 'AT', 1);
|
|
281
296
|
if (mode === 'SET') {
|
|
282
|
-
const functionName = PHP.provideFunction_('lists_set_from_end',
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
297
|
+
const functionName = PHP.provideFunction_('lists_set_from_end', `
|
|
298
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list, $at, $value) {
|
|
299
|
+
$list[count($list) - $at] = $value;
|
|
300
|
+
}
|
|
301
|
+
`);
|
|
287
302
|
return functionName + '(' + list + ', ' + at + ', ' + value + ');\n';
|
|
288
303
|
} else if (mode === 'INSERT') {
|
|
289
|
-
const functionName = PHP.provideFunction_('lists_insert_from_end',
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
304
|
+
const functionName = PHP.provideFunction_('lists_insert_from_end', `
|
|
305
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list, $at, $value) {
|
|
306
|
+
return array_splice($list, count($list) - $at, 0, $value);
|
|
307
|
+
}
|
|
308
|
+
`);
|
|
294
309
|
return functionName + '(' + list + ', ' + at + ', ' + value + ');\n';
|
|
295
310
|
}
|
|
296
311
|
break;
|
|
@@ -382,29 +397,28 @@ PHP['lists_getSublist'] = function(block) {
|
|
|
382
397
|
} else {
|
|
383
398
|
const at1 = PHP.getAdjusted(block, 'AT1');
|
|
384
399
|
const at2 = PHP.getAdjusted(block, 'AT2');
|
|
385
|
-
const functionName = PHP.provideFunction_('lists_get_sublist',
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
]);
|
|
400
|
+
const functionName = PHP.provideFunction_('lists_get_sublist', `
|
|
401
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($list, $where1, $at1, $where2, $at2) {
|
|
402
|
+
if ($where1 == 'FROM_END') {
|
|
403
|
+
$at1 = count($list) - 1 - $at1;
|
|
404
|
+
} else if ($where1 == 'FIRST') {
|
|
405
|
+
$at1 = 0;
|
|
406
|
+
} else if ($where1 != 'FROM_START') {
|
|
407
|
+
throw new Exception('Unhandled option (lists_get_sublist).');
|
|
408
|
+
}
|
|
409
|
+
$length = 0;
|
|
410
|
+
if ($where2 == 'FROM_START') {
|
|
411
|
+
$length = $at2 - $at1 + 1;
|
|
412
|
+
} else if ($where2 == 'FROM_END') {
|
|
413
|
+
$length = count($list) - $at1 - $at2;
|
|
414
|
+
} else if ($where2 == 'LAST') {
|
|
415
|
+
$length = count($list) - $at1;
|
|
416
|
+
} else {
|
|
417
|
+
throw new Exception('Unhandled option (lists_get_sublist).');
|
|
418
|
+
}
|
|
419
|
+
return array_slice($list, $at1, $length);
|
|
420
|
+
}
|
|
421
|
+
`);
|
|
408
422
|
code = functionName + '(' + list + ', \'' + where1 + '\', ' + at1 + ', \'' +
|
|
409
423
|
where2 + '\', ' + at2 + ')';
|
|
410
424
|
}
|
|
@@ -416,16 +430,22 @@ PHP['lists_sort'] = function(block) {
|
|
|
416
430
|
const listCode = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()';
|
|
417
431
|
const direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1;
|
|
418
432
|
const type = block.getFieldValue('TYPE');
|
|
419
|
-
const functionName = PHP.provideFunction_('lists_sort',
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
'
|
|
423
|
-
'
|
|
424
|
-
'
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
433
|
+
const functionName = PHP.provideFunction_('lists_sort', `
|
|
434
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($list, $type, $direction) {
|
|
435
|
+
$sortCmpFuncs = array(
|
|
436
|
+
'NUMERIC' => 'strnatcasecmp',
|
|
437
|
+
'TEXT' => 'strcmp',
|
|
438
|
+
'IGNORE_CASE' => 'strcasecmp'
|
|
439
|
+
);
|
|
440
|
+
$sortCmp = $sortCmpFuncs[$type];
|
|
441
|
+
$list2 = $list;
|
|
442
|
+
usort($list2, $sortCmp);
|
|
443
|
+
if ($direction == -1) {
|
|
444
|
+
$list2 = array_reverse($list2);
|
|
445
|
+
}
|
|
446
|
+
return $list2;
|
|
447
|
+
}
|
|
448
|
+
`);
|
|
429
449
|
const sortCode =
|
|
430
450
|
functionName + '(' + listCode + ', "' + type + '", ' + direction + ')';
|
|
431
451
|
return [sortCode, PHP.ORDER_FUNCTION_CALL];
|
|
@@ -434,12 +454,12 @@ PHP['lists_sort'] = function(block) {
|
|
|
434
454
|
PHP['lists_split'] = function(block) {
|
|
435
455
|
// Block for splitting text into a list, or joining a list into text.
|
|
436
456
|
let value_input = PHP.valueToCode(block, 'INPUT', PHP.ORDER_NONE);
|
|
437
|
-
const value_delim = PHP.valueToCode(block, 'DELIM', PHP.ORDER_NONE) || '
|
|
457
|
+
const value_delim = PHP.valueToCode(block, 'DELIM', PHP.ORDER_NONE) || "''";
|
|
438
458
|
const mode = block.getFieldValue('MODE');
|
|
439
459
|
let functionName;
|
|
440
460
|
if (mode === 'SPLIT') {
|
|
441
461
|
if (!value_input) {
|
|
442
|
-
value_input = '
|
|
462
|
+
value_input = "''";
|
|
443
463
|
}
|
|
444
464
|
functionName = 'explode';
|
|
445
465
|
} else if (mode === 'JOIN') {
|
package/generators/php/math.js
CHANGED
|
@@ -34,7 +34,7 @@ PHP['math_arithmetic'] = function(block) {
|
|
|
34
34
|
'MINUS': [' - ', PHP.ORDER_SUBTRACTION],
|
|
35
35
|
'MULTIPLY': [' * ', PHP.ORDER_MULTIPLICATION],
|
|
36
36
|
'DIVIDE': [' / ', PHP.ORDER_DIVISION],
|
|
37
|
-
'POWER': [' ** ', PHP.ORDER_POWER]
|
|
37
|
+
'POWER': [' ** ', PHP.ORDER_POWER],
|
|
38
38
|
};
|
|
39
39
|
const tuple = OPERATORS[block.getFieldValue('OP')];
|
|
40
40
|
const operator = tuple[0];
|
|
@@ -134,7 +134,7 @@ PHP['math_constant'] = function(block) {
|
|
|
134
134
|
'GOLDEN_RATIO': ['(1 + sqrt(5)) / 2', PHP.ORDER_DIVISION],
|
|
135
135
|
'SQRT2': ['M_SQRT2', PHP.ORDER_ATOMIC],
|
|
136
136
|
'SQRT1_2': ['M_SQRT1_2', PHP.ORDER_ATOMIC],
|
|
137
|
-
'INFINITY': ['INF', PHP.ORDER_ATOMIC]
|
|
137
|
+
'INFINITY': ['INF', PHP.ORDER_ATOMIC],
|
|
138
138
|
};
|
|
139
139
|
return CONSTANTS[block.getFieldValue('CONSTANT')];
|
|
140
140
|
};
|
|
@@ -142,53 +142,55 @@ PHP['math_constant'] = function(block) {
|
|
|
142
142
|
PHP['math_number_property'] = function(block) {
|
|
143
143
|
// Check if a number is even, odd, prime, whole, positive, or negative
|
|
144
144
|
// or if it is divisible by certain number. Returns true or false.
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
const PROPERTIES = {
|
|
146
|
+
'EVEN': ['', ' % 2 == 0', PHP.ORDER_MODULUS, PHP.ORDER_EQUALITY],
|
|
147
|
+
'ODD': ['', ' % 2 == 1', PHP.ORDER_MODULUS, PHP.ORDER_EQUALITY],
|
|
148
|
+
'WHOLE': ['is_int(', ')', PHP.ORDER_NONE, PHP.ORDER_FUNCTION_CALL],
|
|
149
|
+
'POSITIVE': ['', ' > 0', PHP.ORDER_RELATIONAL, PHP.ORDER_RELATIONAL],
|
|
150
|
+
'NEGATIVE': ['', ' < 0', PHP.ORDER_RELATIONAL, PHP.ORDER_RELATIONAL],
|
|
151
|
+
'DIVISIBLE_BY': [null, null, PHP.ORDER_MODULUS, PHP.ORDER_EQUALITY],
|
|
152
|
+
'PRIME': [null, null, PHP.ORDER_NONE, PHP.ORDER_FUNCTION_CALL],
|
|
153
|
+
};
|
|
154
|
+
const dropdownProperty = block.getFieldValue('PROPERTY');
|
|
155
|
+
const [prefix, suffix, inputOrder, outputOrder] = PROPERTIES[dropdownProperty];
|
|
156
|
+
const numberToCheck = PHP.valueToCode(block, 'NUMBER_TO_CHECK',
|
|
157
|
+
inputOrder) || '0';
|
|
148
158
|
let code;
|
|
149
|
-
if (
|
|
159
|
+
if (dropdownProperty === 'PRIME') {
|
|
150
160
|
// Prime is a special case as it is not a one-liner test.
|
|
151
|
-
const functionName = PHP.provideFunction_('math_isPrime',
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
' // And false if n is divisible by 2 or 3.',
|
|
157
|
-
' if (!is_numeric($n) || $n <= 1 || $n % 1 != 0 || $n % 2 == 0 ||' +
|
|
158
|
-
' $n % 3 == 0) {',
|
|
159
|
-
' return false;', ' }',
|
|
160
|
-
' // Check all the numbers of form 6k +/- 1, up to sqrt(n).',
|
|
161
|
-
' for ($x = 6; $x <= sqrt($n) + 1; $x += 6) {',
|
|
162
|
-
' if ($n % ($x - 1) == 0 || $n % ($x + 1) == 0) {',
|
|
163
|
-
' return false;', ' }', ' }', ' return true;', '}'
|
|
164
|
-
]);
|
|
165
|
-
code = functionName + '(' + number_to_check + ')';
|
|
166
|
-
return [code, PHP.ORDER_FUNCTION_CALL];
|
|
161
|
+
const functionName = PHP.provideFunction_('math_isPrime', `
|
|
162
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($n) {
|
|
163
|
+
// https://en.wikipedia.org/wiki/Primality_test#Naive_methods
|
|
164
|
+
if ($n == 2 || $n == 3) {
|
|
165
|
+
return true;
|
|
167
166
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
break;
|
|
178
|
-
case 'POSITIVE':
|
|
179
|
-
code = number_to_check + ' > 0';
|
|
180
|
-
break;
|
|
181
|
-
case 'NEGATIVE':
|
|
182
|
-
code = number_to_check + ' < 0';
|
|
183
|
-
break;
|
|
184
|
-
case 'DIVISIBLE_BY': {
|
|
185
|
-
const divisor =
|
|
186
|
-
PHP.valueToCode(block, 'DIVISOR', PHP.ORDER_MODULUS) || '0';
|
|
187
|
-
code = number_to_check + ' % ' + divisor + ' == 0';
|
|
188
|
-
break;
|
|
167
|
+
// False if n is NaN, negative, is 1, or not whole.
|
|
168
|
+
// And false if n is divisible by 2 or 3.
|
|
169
|
+
if (!is_numeric($n) || $n <= 1 || $n % 1 != 0 || $n % 2 == 0 || $n % 3 == 0) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
// Check all the numbers of form 6k +/- 1, up to sqrt(n).
|
|
173
|
+
for ($x = 6; $x <= sqrt($n) + 1; $x += 6) {
|
|
174
|
+
if ($n % ($x - 1) == 0 || $n % ($x + 1) == 0) {
|
|
175
|
+
return false;
|
|
189
176
|
}
|
|
190
177
|
}
|
|
191
|
-
return
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
`);
|
|
181
|
+
code = functionName + '(' + numberToCheck + ')';
|
|
182
|
+
} else if (dropdownProperty === 'DIVISIBLE_BY') {
|
|
183
|
+
const divisor = PHP.valueToCode(block, 'DIVISOR',
|
|
184
|
+
PHP.ORDER_MODULUS) || '0';
|
|
185
|
+
if (divisor === '0') {
|
|
186
|
+
return ['false', PHP.ORDER_ATOMIC];
|
|
187
|
+
|
|
188
|
+
}
|
|
189
|
+
code = numberToCheck + ' % ' + divisor + ' == 0';
|
|
190
|
+
} else {
|
|
191
|
+
code = prefix + numberToCheck + suffix;
|
|
192
|
+
}
|
|
193
|
+
return [code, outputOrder];
|
|
192
194
|
};
|
|
193
195
|
|
|
194
196
|
PHP['math_change'] = function(block) {
|
|
@@ -226,23 +228,23 @@ PHP['math_on_list'] = function(block) {
|
|
|
226
228
|
code = 'max(' + list + ')';
|
|
227
229
|
break;
|
|
228
230
|
case 'AVERAGE': {
|
|
229
|
-
const functionName = PHP.provideFunction_('math_mean',
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
231
|
+
const functionName = PHP.provideFunction_('math_mean', `
|
|
232
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($myList) {
|
|
233
|
+
return array_sum($myList) / count($myList);
|
|
234
|
+
}
|
|
235
|
+
`);
|
|
233
236
|
list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()';
|
|
234
237
|
code = functionName + '(' + list + ')';
|
|
235
238
|
break;
|
|
236
239
|
}
|
|
237
240
|
case 'MEDIAN': {
|
|
238
|
-
const functionName = PHP.provideFunction_('math_median',
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
]);
|
|
241
|
+
const functionName = PHP.provideFunction_('math_median', `
|
|
242
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($arr) {
|
|
243
|
+
sort($arr,SORT_NUMERIC);
|
|
244
|
+
return (count($arr) % 2) ? $arr[floor(count($arr) / 2)] :
|
|
245
|
+
($arr[floor(count($arr) / 2)] + $arr[floor(count($arr) / 2) - 1]) / 2;
|
|
246
|
+
}
|
|
247
|
+
`);
|
|
246
248
|
list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || '[]';
|
|
247
249
|
code = functionName + '(' + list + ')';
|
|
248
250
|
break;
|
|
@@ -251,36 +253,40 @@ PHP['math_on_list'] = function(block) {
|
|
|
251
253
|
// As a list of numbers can contain more than one mode,
|
|
252
254
|
// the returned result is provided as an array.
|
|
253
255
|
// Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1].
|
|
254
|
-
const functionName = PHP.provideFunction_('math_modes',
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
256
|
+
const functionName = PHP.provideFunction_('math_modes', `
|
|
257
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($values) {
|
|
258
|
+
if (empty($values)) return array();
|
|
259
|
+
$counts = array_count_values($values);
|
|
260
|
+
arsort($counts); // Sort counts in descending order
|
|
261
|
+
$modes = array_keys($counts, current($counts), true);
|
|
262
|
+
return $modes;
|
|
263
|
+
}
|
|
264
|
+
`);
|
|
262
265
|
list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || '[]';
|
|
263
266
|
code = functionName + '(' + list + ')';
|
|
264
267
|
break;
|
|
265
268
|
}
|
|
266
269
|
case 'STD_DEV': {
|
|
267
|
-
const functionName = PHP.provideFunction_('math_standard_deviation',
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
270
|
+
const functionName = PHP.provideFunction_('math_standard_deviation', `
|
|
271
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($numbers) {
|
|
272
|
+
$n = count($numbers);
|
|
273
|
+
if (!$n) return null;
|
|
274
|
+
$mean = array_sum($numbers) / count($numbers);
|
|
275
|
+
foreach($numbers as $key => $num) $devs[$key] = pow($num - $mean, 2);
|
|
276
|
+
return sqrt(array_sum($devs) / (count($devs) - 1));
|
|
277
|
+
}
|
|
278
|
+
`);
|
|
275
279
|
list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || '[]';
|
|
276
280
|
code = functionName + '(' + list + ')';
|
|
277
281
|
break;
|
|
278
282
|
}
|
|
279
283
|
case 'RANDOM': {
|
|
280
|
-
const functionName = PHP.provideFunction_('math_random_list',
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
+
const functionName = PHP.provideFunction_('math_random_list', `
|
|
285
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($list) {
|
|
286
|
+
$x = rand(0, count($list)-1);
|
|
287
|
+
return $list[$x];
|
|
288
|
+
}
|
|
289
|
+
`);
|
|
284
290
|
list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || '[]';
|
|
285
291
|
code = functionName + '(' + list + ')';
|
|
286
292
|
break;
|
|
@@ -315,11 +321,14 @@ PHP['math_random_int'] = function(block) {
|
|
|
315
321
|
// Random integer between [X] and [Y].
|
|
316
322
|
const argument0 = PHP.valueToCode(block, 'FROM', PHP.ORDER_NONE) || '0';
|
|
317
323
|
const argument1 = PHP.valueToCode(block, 'TO', PHP.ORDER_NONE) || '0';
|
|
318
|
-
const functionName = PHP.provideFunction_('math_random_int',
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
324
|
+
const functionName = PHP.provideFunction_('math_random_int', `
|
|
325
|
+
function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($a, $b) {
|
|
326
|
+
if ($a > $b) {
|
|
327
|
+
return rand($b, $a);
|
|
328
|
+
}
|
|
329
|
+
return rand($a, $b);
|
|
330
|
+
}
|
|
331
|
+
`);
|
|
323
332
|
const code = functionName + '(' + argument0 + ', ' + argument1 + ')';
|
|
324
333
|
return [code, PHP.ORDER_FUNCTION_CALL];
|
|
325
334
|
};
|