33import { addExtraBlocks } from './extra_blocks' ;
44import { getStandardBlocklyBlocks } from './standard_blockly_blocks' ;
55import { getStandardScratchBlocks } from './standard_scratch_blocks' ;
6+ import { Block , BlockType } from '../../task/blocks/block_types' ;
67
78let blocklySets = {
89 allDefault : {
@@ -67,7 +68,7 @@ function addInSet(l, val) {
6768 }
6869}
6970
70- class BlocklyInterface {
71+ export class BlocklyHelper {
7172 private subTask : any ;
7273 private scratchMode : boolean ;
7374 private maxBlocks : number ;
@@ -92,6 +93,7 @@ class BlocklyInterface {
9293 private quickAlgoInterface : any ;
9394 private highlightedBlocks : any [ ] ;
9495 private includeBlocks : any ;
96+ private availableBlocks : Block [ ] ;
9597 private mainContext : any ;
9698 private placeholderBlocks : boolean ;
9799 private strings : any ;
@@ -100,6 +102,7 @@ class BlocklyInterface {
100102 private blockCounts : any ;
101103 private dragJustTerminated : boolean ;
102104 private prevWidth : number ;
105+ private availableBlocksInfo : Record < string , Record < string , Record < string , Block > > > = { } ;
103106
104107 constructor ( maxBlocks , subTask ) {
105108 this . subTask = subTask ;
@@ -147,7 +150,7 @@ class BlocklyInterface {
147150
148151 loadContext ( mainContext ) {
149152 this . mainContext = mainContext ;
150- this . createGeneratorsAndBlocks ( ) ;
153+ // this.createGeneratorsAndBlocks();
151154 }
152155
153156 load ( locale , display , nbTestCases , options ) {
@@ -327,6 +330,11 @@ class BlocklyInterface {
327330 this . includeBlocks = includeBlocks ;
328331 }
329332
333+ setAvailableBlocks ( availableBlocks : Block [ ] ) {
334+ this . availableBlocks = availableBlocks ;
335+ this . createGeneratorsAndBlocksForAvailableBlocks ( ) ;
336+ }
337+
330338 getEmptyContent ( ) {
331339 if ( this . scratchMode ) {
332340 return '<xml><block type="robot_start" deletable="false" movable="false" x="10" y="20"></block></xml>' ;
@@ -402,7 +410,8 @@ class BlocklyInterface {
402410
403411 this . programs [ this . codeId ] . blockly = window . Blockly . Xml . domToText ( xml ) ;
404412 this . programs [ this . codeId ] . blocklyJS = this . getCode ( "javascript" ) ;
405- //this.programs[this.codeId].blocklyPython = this.getCode("python");
413+ this . programs [ this . codeId ] . blocklyPython = this . getCode ( "python" ) ;
414+ console . log ( 'python' , this . programs [ this . codeId ] . blocklyPython )
406415 }
407416 }
408417
@@ -428,6 +437,7 @@ class BlocklyInterface {
428437 window . jQuery ( "#program" ) . val ( this . programs [ this . codeId ] . javascript ) ;
429438 }
430439
440+ // Used by some Quickalgo libraries
431441 updateSize ( force ) {
432442 let panelWidth = 500 ;
433443 if ( this . languages [ this . codeId ] == "blockly" ) {
@@ -845,10 +855,10 @@ class BlocklyInterface {
845855 let blockParams = blockInfo . params ;
846856
847857 for ( let language in { JavaScript : null , Python : null } ) {
848- if ( typeof blockInfo . codeGenerators [ language ] == "undefined" ) {
849- // Prevent the function name to be used as a variable
850- window . Blockly [ language ] . addReservedWords ( code ) ;
858+ // Prevent the function name to be used as a variable
859+ window . Blockly [ language ] . addReservedWords ( code ) ;
851860
861+ if ( typeof blockInfo . codeGenerators [ language ] == "undefined" ) {
852862 function setCodeGeneratorForLanguage ( language ) {
853863 blockInfo . codeGenerators [ language ] = function ( block ) {
854864 let params = "" ;
@@ -1063,6 +1073,36 @@ class BlocklyInterface {
10631073 //this.createBlock(label, generator.labelFr, generator.type, generator.nbParams);
10641074 }
10651075 }
1076+
1077+ }
1078+
1079+ createGeneratorsAndBlocksForAvailableBlocks ( ) {
1080+ console . log ( 'av blocks' , this . availableBlocks ) ;
1081+ for ( let block of this . availableBlocks . filter ( block => block . type === BlockType . Function ) ) {
1082+ const { generatorName, category, name} = block ;
1083+
1084+ this . availableBlocksInfo [ generatorName ] ??= { } ;
1085+ this . availableBlocksInfo [ generatorName ] [ category ] ??= { } ;
1086+ this . availableBlocksInfo [ generatorName ] [ category ] [ name ] = {
1087+ ...block ,
1088+ } ;
1089+
1090+ const blockInfo = this . availableBlocksInfo [ generatorName ] [ category ] [ name ] ;
1091+
1092+ /* TODO: Allow library writers to provide their own JS/Python code instead of just a handler */
1093+ this . completeBlockHandler ( blockInfo , generatorName , this . mainContext ) ;
1094+ this . completeBlockJson ( blockInfo , generatorName , category , this . mainContext ) ; /* category.category is category name */
1095+ this . completeBlockXml ( blockInfo ) ;
1096+ this . completeCodeGenerators ( blockInfo , generatorName ) ;
1097+ this . applyCodeGenerators ( blockInfo ) ;
1098+ this . createBlock ( blockInfo ) ;
1099+ this . applyBlockOptions ( blockInfo ) ;
1100+ }
1101+
1102+ // TODO: code generators for customClasses and customClassInstances
1103+ for ( let block of this . availableBlocks . filter ( block => block . type === BlockType . ClassFunction ) ) {
1104+ console . log ( 'create code generator' , block ) ;
1105+ }
10661106 }
10671107
10681108 getBlocklyLibCode ( generators ) {
@@ -1163,6 +1203,20 @@ class BlocklyInterface {
11631203 return null ;
11641204 }
11651205
1206+ getBlockFromCustomBlocks ( generatorName : string , category : string , name : string ) {
1207+ if ( ! ( generatorName in this . availableBlocksInfo ) ) {
1208+ throw new Error ( `Generator not found: ${ generatorName } ` ) ;
1209+ }
1210+ if ( ! ( category in this . availableBlocksInfo [ generatorName ] ) ) {
1211+ throw new Error ( `Category not found in generator ${ generatorName } : ${ category } ` ) ;
1212+ }
1213+ if ( ! ( name in this . availableBlocksInfo [ generatorName ] [ category ] ) ) {
1214+ throw new Error ( `Block not found in generator ${ generatorName } and category ${ category } : ${ name } ` ) ;
1215+ }
1216+
1217+ return this . availableBlocksInfo [ generatorName ] [ category ] [ name ] ;
1218+ }
1219+
11661220
11671221 addBlocksAndCategories ( blockNames , blocksDefinition , categoriesInfos ) {
11681222 let colours = this . getDefaultColours ( ) ;
@@ -1208,45 +1262,55 @@ class BlocklyInterface {
12081262 this . addBlocksAllowed ( [ 'math_number' , 'text' ] ) ;
12091263 }
12101264
1265+ console . log ( 'available' , this . availableBlocks ) ;
12111266
12121267 // *** Blocks from the lib
1213- if ( this . includeBlocks . generatedBlocks && 'wholeCategories' in this . includeBlocks . generatedBlocks ) {
1214- for ( let blockType in this . includeBlocks . generatedBlocks . wholeCategories ) {
1215- let categories = this . includeBlocks . generatedBlocks . wholeCategories [ blockType ] ;
1216- for ( let i = 0 ; i < categories . length ; i ++ ) {
1217- let category = categories [ i ] ;
1218- if ( blockType in this . mainContext . customBlocks && category in this . mainContext . customBlocks [ blockType ] ) {
1219- let contextBlocks = this . mainContext . customBlocks [ blockType ] [ category ] ;
1220- let blockNames = [ ] ;
1221- for ( let i = 0 ; i < contextBlocks . length ; i ++ ) {
1222- blockNames . push ( contextBlocks [ i ] . name ) ;
1223- }
1224- this . addBlocksAndCategories (
1225- blockNames ,
1226- this . mainContext . customBlocks [ blockType ] ,
1227- categoriesInfos
1228- ) ;
1229- }
1230- }
1268+ for ( let block of this . availableBlocks ) {
1269+ if ( BlockType . Function !== block . type ) {
1270+ continue ;
12311271 }
1232- }
1233- if ( this . includeBlocks . generatedBlocks && 'singleBlocks' in this . includeBlocks . generatedBlocks ) {
1234- for ( let blockType in this . includeBlocks . generatedBlocks . singleBlocks ) {
1235- this . addBlocksAndCategories (
1236- this . includeBlocks . generatedBlocks . singleBlocks [ blockType ] ,
1237- this . mainContext . customBlocks [ blockType ] ,
1238- categoriesInfos
1239- ) ;
1272+
1273+ let colours = this . getDefaultColours ( ) ;
1274+ const blockInfo = this . getBlockFromCustomBlocks ( block . generatorName , block . category , block . name ) ;
1275+
1276+ if ( ! ( block . category in categoriesInfos ) ) {
1277+ categoriesInfos [ block . category ] = {
1278+ blocksXml : [ ] ,
1279+ colour : colours . blocks [ block . name ]
1280+ } ;
1281+ }
1282+ let blockXml = blockInfo . blocklyXml ;
1283+ if ( categoriesInfos [ block . category ] . blocksXml . indexOf ( blockXml ) == - 1 ) {
1284+ categoriesInfos [ block . category ] . blocksXml . push ( blockXml ) ;
1285+ }
1286+ this . addBlocksAllowed ( [ block . name ] ) ;
1287+
1288+ // by the way, just change the defaul colours of the blockly blocks:
1289+ if ( ! this . scratchMode ) {
1290+ let defCat = [ "logic" , "loops" , "math" , "texts" , "lists" , "colour" ] ;
1291+ for ( let iCat in defCat ) {
1292+ window . Blockly . Blocks [ defCat [ iCat ] ] . HUE = colours . categories [ defCat [ iCat ] ] ;
1293+ }
12401294 }
12411295 }
1242- for ( let blockType in this . includeBlocks . generatedBlocks ) {
1243- if ( blockType == 'wholeCategories' || blockType == 'singleBlocks' ) continue ;
1244- this . addBlocksAndCategories (
1245- this . includeBlocks . generatedBlocks [ blockType ] ,
1246- this . mainContext . customBlocks [ blockType ] ,
1247- categoriesInfos
1248- ) ;
1249- }
1296+
1297+ // if (this.includeBlocks.generatedBlocks && 'singleBlocks' in this.includeBlocks.generatedBlocks) {
1298+ // for (let blockType in this.includeBlocks.generatedBlocks.singleBlocks) {
1299+ // this.addBlocksAndCategories(
1300+ // this.includeBlocks.generatedBlocks.singleBlocks[blockType],
1301+ // this.mainContext.customBlocks[blockType],
1302+ // categoriesInfos
1303+ // );
1304+ // }
1305+ // }
1306+ // for (let blockType in this.includeBlocks.generatedBlocks) {
1307+ // if (blockType == 'wholeCategories' || blockType == 'singleBlocks') continue;
1308+ // this.addBlocksAndCategories(
1309+ // this.includeBlocks.generatedBlocks[blockType],
1310+ // this.mainContext.customBlocks[blockType],
1311+ // categoriesInfos
1312+ // );
1313+ // }
12501314
12511315 for ( let genName in this . simpleGenerators ) {
12521316 for ( let iGen = 0 ; iGen < this . simpleGenerators [ genName ] . length ; iGen ++ ) {
@@ -1667,7 +1731,3 @@ class BlocklyInterface {
16671731 }
16681732 }
16691733}
1670-
1671- export function getBlocklyHelper ( maxBlocks , subTask ) {
1672- return new BlocklyInterface ( maxBlocks , subTask ) ;
1673- }
0 commit comments