Skip to content

Commit

Permalink
Feature: Recipe Random Command Group (#532)
Browse files Browse the repository at this point in the history
  • Loading branch information
negue authored Oct 27, 2022
1 parent 822ea6c commit 91f3a7b
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 55 deletions.
111 changes: 111 additions & 0 deletions projects/recipe-core/src/lib/command-blocks.generic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import {generateCodeByStep, RecipeCommandBlockRegistry} from "./recipe.types";
import {generateRandomCharacters} from "./utils";

export function registerGenericCommandBlocks(
registry: RecipeCommandBlockRegistry,
generateCodeByStep: generateCodeByStep
): void {
registry["sleepSeconds"] = {
pickerLabel: "Wait for Seconds",
commandGroup: "generic",
configArguments: [
{
name: "seconds",
label: "Seconds",
type: "number"
}
],
toScriptCode: (step, context) => `sleep.secondsAsync(${step.payload.seconds});`,
commandEntryLabelAsync: (queries, payload, parentStep) => {
return Promise.resolve(`sleep: ${payload.seconds} seconds`);
},
entryIcon: () => 'hourglass_top'
};


registry["sleepMs"] = {
pickerLabel: "Wait for Milliseconds",
commandGroup: "generic",
configArguments: [
{
name: "ms",
label: "Milliseconds",
type: "number"
}
],
toScriptCode: (step, context) => `sleep.msAsync(${step.payload.ms});`,
commandEntryLabelAsync: (queries, payload, parentStep) => {
return Promise.resolve(`sleep: ${payload.ms}ms`);
},
entryIcon: () => 'hourglass_top'
};

registry["randomCommandGroup"] = {
pickerLabel: "Random Command Group",
commandGroup: "generic",
configArguments: [
{
name: 'amountOfGroups',
label: 'Amount of Groups',
type: "number"
}
],
extendCommandBlockOnEdit: true,
extendCommandBlock: (step) => {
const amountOfGroups = step.payload.amountOfGroups as number;

if (step.subCommandBlocks.length === amountOfGroups) {
return;
}

if (amountOfGroups < step.subCommandBlocks.length) {
step.subCommandBlocks.length = amountOfGroups;
return;
}


const newSubCommandBlockArray = [...step.subCommandBlocks];

for (let i = step.subCommandBlocks.length; i < amountOfGroups; i++) {
newSubCommandBlockArray.push({
labelId: generateRandomCharacters(5),
entries: []
});
}

step.subCommandBlocks = newSubCommandBlockArray
},
subCommandBlockLabelAsync: (queries, commandBlock, labelId) => {
return Promise.resolve('');
},
awaitCodeHandledInternally: true,
toScriptCode: (step, context, userData) => {
const awaitCode = step.awaited ? 'await ' : '';

const functionNames: string[] = [];

const generatedFunctions = generateCodeByStep(step, context, userData).map(g => {

const functionName = `randomGroup_${g.subCommand.labelId}`;

functionNames.push(functionName);

return `async function ${functionName}() {
${g.generatedScript}
}`;
}).join('\r\n');

return `
${awaitCode} (() => {
${generatedFunctions}
const functionsToChoose = [${functionNames.join(',')}];
return utils.randomElement(functionsToChoose)();
})();`;
},
commandEntryLabelAsync: (queries, payload, parentStep) => {
return 'trigger any of these command groups randomly';
}
};
}
2 changes: 1 addition & 1 deletion projects/recipe-core/src/lib/command-blocks.memebox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export function registerMemeboxCommandBlocks(

return `${createMemeboxApiVariable(actionPayload)}
.triggerWhile(async (helpers_${step.payload._suffix}) => {
${generateCodeByStep(step, context, userData)}
${generateCodeByStep(step, context, userData)[0].generatedScript}
}
${actionOverrides ? ',' + JSON.stringify(actionOverrides) : ''});`;
},
Expand Down
39 changes: 26 additions & 13 deletions projects/recipe-core/src/lib/generateCodeByRecipe.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,67 @@
import {RecipeContext, RecipeEntry, RecipeEntryCommandCall, RecipeEntryCommandPayload} from "./recipe.types";
import {
generatedCodeBySubCommandBlock,
RecipeContext,
RecipeEntry,
RecipeEntryCommandCall,
RecipeEntryCommandPayload
} from "./recipe.types";
import {uuid} from "@gewd/utils";
import {registerMemeboxCommandBlocks} from "./command-blocks.memebox";
import {registerObsCommandBlocks} from "./command-blocks.obs";
import {registerTwitchCommandBlocks} from "./command-blocks.twitch";
import {UserDataState} from "@memebox/contracts";
import {RecipeCommandRegistry} from "./recipeCommandRegistry";
import {registerGenericCommandBlocks} from "./command-blocks.generic";


function generateCodeByStepAsync (step: RecipeEntry, context: RecipeContext, userData: UserDataState): string {
const result: string[] = [];
function generateCodeByStepAsync (step: RecipeEntry, context: RecipeContext, userData: UserDataState): generatedCodeBySubCommandBlock[] {
const result: generatedCodeBySubCommandBlock[] = [];

for (const subStepInfo of step.subCommandBlocks) {
const scriptCode: string[] = [];

for (const entryId of subStepInfo.entries) {
const subEntry = context.entries[entryId];

if (!subEntry) {
result.push(`logger.error('this shouldnt have happened: cant find command block information of ${entryId});`);
scriptCode.push(`logger.error('this shouldnt have happened: cant find command block information of ${entryId});`);
} else if (subEntry.entryType === 'command'){
const entryDefinition = RecipeCommandRegistry[subEntry.commandBlockType];

// result.push(`logger.log('Pre: ${subEntry.commandType}');`);

if (!entryDefinition.awaitCodeHandledInternally && subEntry.awaited) {
result.push('await ');
scriptCode.push('await ');
}

const createdStepCode = entryDefinition.toScriptCode(subEntry, context, userData);

result.push(createdStepCode.trim());
scriptCode.push(createdStepCode.trim());

// result.push(`logger.log('Post: ${subEntry.commandType}');`);
} else {
result.push('TODO FOR TYPE: '+subEntry.entryType);
scriptCode.push('TODO FOR TYPE: '+subEntry.entryType);
}
}

result.push({
generatedScript: scriptCode.join('\r\n'),
subCommand: subStepInfo
});
}

return result.join('\r\n');
return result;

}

export function generateCodeByRecipe(
recipeContext: RecipeContext, userData: UserDataState
): string {
const result: string[] = [];

const rootEntry = recipeContext.entries[recipeContext.rootEntry];

result.push(generateCodeByStepAsync(rootEntry, recipeContext, userData));

return result.join('\r\n');
return generateCodeByStepAsync(rootEntry, recipeContext, userData)
.map(g => g.generatedScript)
.join('\r\n');
}

export function generateRecipeEntryCommandCall (
Expand All @@ -66,6 +78,7 @@ export function generateRecipeEntryCommandCall (
};
}

registerGenericCommandBlocks(RecipeCommandRegistry, generateCodeByStepAsync);
registerMemeboxCommandBlocks(RecipeCommandRegistry, generateCodeByStepAsync);
registerObsCommandBlocks(RecipeCommandRegistry);
registerTwitchCommandBlocks(RecipeCommandRegistry);
18 changes: 12 additions & 6 deletions projects/recipe-core/src/lib/recipe.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ export interface RecipeCommandInfo {

// at some point custom controls/ui for each stepInfo could be shown

export interface RecipeSubCommandBlock {
labelId: string;
entries: string[] // entryId
}

export interface RecipeEntryBase {
id: string;
awaited?: boolean;
subCommandBlocks: {
labelId: string;
entries: string[] // entryId
}[];
subCommandBlocks: RecipeSubCommandBlock[];
}

export interface RecipeEntryCommandPayload {
Expand Down Expand Up @@ -112,6 +114,7 @@ export interface RecipeCommandDefinition {
allowedToBeAdded?: (step: RecipeEntry, context: RecipeContext) => boolean;
toScriptCode: (step: RecipeEntryCommandCall, context: RecipeContext, userData: UserDataState) => string;
awaitCodeHandledInternally?: boolean;
extendCommandBlockOnEdit?: boolean;
commandType?: string;
}

Expand All @@ -123,5 +126,8 @@ export interface RecipeCommandSelectionGroup {
export interface RecipeCommandBlockRegistry {
[stepType: string]: RecipeCommandDefinition
}

export type generateCodeByStep = (step: RecipeEntry, context: RecipeContext, userData: UserDataState) => string;
export interface generatedCodeBySubCommandBlock {
subCommand: RecipeSubCommandBlock;
generatedScript: string;
}
export type generateCodeByStep = (step: RecipeEntry, context: RecipeContext, userData: UserDataState) => generatedCodeBySubCommandBlock[];
33 changes: 1 addition & 32 deletions projects/recipe-core/src/lib/recipeCommandRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,5 @@
import {RecipeCommandBlockRegistry} from "./recipe.types";

export const RecipeCommandRegistry: RecipeCommandBlockRegistry = {
"sleepSeconds": {
pickerLabel: "Wait for Seconds",
commandGroup: "generic",
configArguments: [
{
name: "seconds",
label: "Seconds",
type: "number"
}
],
toScriptCode: (step, context) => `sleep.secondsAsync(${step.payload.seconds});`,
commandEntryLabelAsync: (queries, payload, parentStep) => {
return Promise.resolve(`sleep: ${payload.seconds} seconds`);
},
entryIcon: () => 'hourglass_top'
},
"sleepMs": {
pickerLabel: "Wait for Milliseconds",
commandGroup: "generic",
configArguments: [
{
name: "ms",
label: "Milliseconds",
type: "number"
}
],
toScriptCode: (step, context) => `sleep.msAsync(${step.payload.ms});`,
commandEntryLabelAsync: (queries, payload, parentStep) => {
return Promise.resolve(`sleep: ${payload.ms}ms`);
},
entryIcon: () => 'hourglass_top'
}

};
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@

</ng-container>


<div cdkDropList class="entry-list"
*ngFor="let subStepInfo of entry | getEntrySubBlockInfoArray$ | async"
(cdkDropListDropped)="stepRearranged($event, subStepInfo)">
Expand Down
19 changes: 17 additions & 2 deletions projects/recipe-ui/src/lib/recipe-block/recipe-block.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ChangeDetectorRef, Component, HostBinding, Input, OnDestroy, OnInit} from '@angular/core';
import {RecipeEntry, RecipeEntryCommandCall, RecipeSubCommandInfo} from "@memebox/recipe-core";
import {RecipeCommandRegistry, RecipeEntry, RecipeEntryCommandCall, RecipeSubCommandInfo} from "@memebox/recipe-core";
import {CdkDragDrop} from "@angular/cdk/drag-drop";
import {RecipeContextDirective} from "../recipe-context.directive";
import {DialogService} from "../../../../../src/app/shared/dialogs/dialog.service";
Expand Down Expand Up @@ -105,7 +105,22 @@ export class RecipeBlockComponent
const newPayload = await this.stepCreator.editStepData(entry, this.context.recipe!);

if (newPayload) {
this.context.changePayload(entry, newPayload);
if (RecipeCommandRegistry[entry.commandBlockType].extendCommandBlockOnEdit) {
const newEntry = {
...entry,
payload:newPayload,
subCommandBlocks: [...entry.subCommandBlocks]
};

RecipeCommandRegistry[entry.commandBlockType]?.extendCommandBlock?.(newEntry, parent)

this.context.changeEntry(newEntry);
}
else {

this.context.changePayload(entry, newPayload);
}

}
}
}
6 changes: 6 additions & 0 deletions projects/recipe-ui/src/lib/recipe-context.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,10 @@ export class RecipeContextDirective
}
});
}

changeEntry(entry: RecipeEntryCommandCall): void{
this.update(state => {
state.entries[entry.id] = entry;
})
}
}

0 comments on commit 91f3a7b

Please sign in to comment.