maze-blockly-wrapper 0.7.6 → 0.7.13
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/README.md +63 -7
- package/dist/components/MusicDemo.d.ts +3 -0
- package/dist/components/music/GameControls.d.ts +11 -0
- package/dist/components/music/MusicBlocklyContainer.d.ts +41 -0
- package/dist/components/music/MusicCanvas.d.ts +14 -0
- package/dist/components/music/MusicEditor.d.ts +11 -0
- package/dist/components/music/MusicGame.d.ts +15 -0
- package/dist/components/music/MusicTabs.d.ts +21 -0
- package/dist/components/music/MusicVisualEditor.d.ts +14 -0
- package/dist/components/music/NoteDialog.d.ts +14 -0
- package/dist/components/music/audioEngine.d.ts +54 -0
- package/dist/components/music/blockly-messages.d.ts +5 -0
- package/dist/components/music/blocks.d.ts +4 -0
- package/dist/components/music/fields/FieldMusicNote.d.ts +2 -0
- package/dist/components/music/graphicsConfig.d.ts +3 -0
- package/dist/components/music/index.d.ts +12 -0
- package/dist/components/music/types.d.ts +76 -0
- package/dist/index.cjs.js +4427 -231
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.esm.js +4429 -233
- package/dist/index.esm.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -131,16 +131,72 @@ interface MazeConfig {
|
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
### RunResult
|
|
134
|
+
Each game component returns a result object via the `onRunFinish` callback when specific conditions are met.
|
|
134
135
|
|
|
136
|
+
#### MazeGame Result
|
|
137
|
+
**When sent:** Triggered when the spider reaches the finish line OR when maximum moves are exceeded.
|
|
135
138
|
```typescript
|
|
136
139
|
interface RunResult {
|
|
137
|
-
steps: number;
|
|
138
|
-
reachedFinish: boolean;
|
|
139
|
-
maxMovesExceeded: boolean;
|
|
140
|
-
finalPosition: Position;
|
|
141
|
-
path: Position[];
|
|
142
|
-
executionTime: number;
|
|
143
|
-
|
|
140
|
+
steps: number; // Number of steps taken
|
|
141
|
+
reachedFinish: boolean; // True if spider reached the finish cell
|
|
142
|
+
maxMovesExceeded: boolean; // True if maxMoves limit was hit
|
|
143
|
+
finalPosition: Position; // Where the spider ended up
|
|
144
|
+
path: Position[]; // Array of positions visited (todo)
|
|
145
|
+
executionTime: number; // Time in ms (todo)
|
|
146
|
+
inventory: string[]; // Collected items (COIN, KEY, etc.)
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### FilmGame Result
|
|
151
|
+
**When sent:** Triggered when the user clicks the "Finish" button to check their movie against the target.
|
|
152
|
+
```typescript
|
|
153
|
+
interface RunResult {
|
|
154
|
+
commands: number; // Total drawing commands used
|
|
155
|
+
reachedTarget: boolean; // True if accuracy > 80%
|
|
156
|
+
maxCommandsExceeded: boolean;
|
|
157
|
+
shapes: Shape[]; // Array of shapes drawn by student
|
|
158
|
+
executionTime: number; // Time in ms
|
|
159
|
+
accuracy: number; // 0-1 score representing similarity to target
|
|
160
|
+
tickCount: number; // Final tick count
|
|
161
|
+
comparisonResult: { // Detailed breakdown
|
|
162
|
+
shapeCountMatch: boolean;
|
|
163
|
+
shapeTypesMatch: boolean;
|
|
164
|
+
positionAccuracy: number;
|
|
165
|
+
sizeAccuracy: number;
|
|
166
|
+
colorAccuracy: number;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### DrawingGame Result
|
|
172
|
+
**When sent:** Triggered automatically when code execution completes.
|
|
173
|
+
```typescript
|
|
174
|
+
interface RunResult {
|
|
175
|
+
commands: number; // Total commands executed
|
|
176
|
+
reachedTarget: boolean; // True if game state marked as won (custom logic)
|
|
177
|
+
maxCommandsExceeded: boolean;
|
|
178
|
+
finalPosition: Position; // Final pen position
|
|
179
|
+
drawnPath: Position[]; // Array of points visited by pen
|
|
180
|
+
executionTime: number; // Time in ms
|
|
181
|
+
accuracy: number; // 0-1 score comparing drawn path to target path
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### MusicGame Result
|
|
186
|
+
**When sent:** Triggered automatically when the music finishes playing.
|
|
187
|
+
```typescript
|
|
188
|
+
interface RunResult {
|
|
189
|
+
commands: number; // Total notes/pauses played
|
|
190
|
+
reachedTarget: boolean; // True if accuracy is 100%
|
|
191
|
+
maxCommandsExceeded: boolean;
|
|
192
|
+
notes: Note[]; // Array of notes played
|
|
193
|
+
executionTime: number; // Playback time in ms
|
|
194
|
+
accuracy: number; // 0-100 score comparing played notes to editor notes
|
|
195
|
+
comparisonResult: {
|
|
196
|
+
noteCountMatch: boolean;
|
|
197
|
+
melodyAccuracy: number; // Pitch/Duration match score
|
|
198
|
+
rhythmAccuracy: number; // Timing match score
|
|
199
|
+
};
|
|
144
200
|
}
|
|
145
201
|
```
|
|
146
202
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface GameControlsProps {
|
|
3
|
+
isPlaying: boolean;
|
|
4
|
+
isPaused: boolean;
|
|
5
|
+
onPlay: () => void;
|
|
6
|
+
onPause: () => void;
|
|
7
|
+
onStop: () => void;
|
|
8
|
+
onReset: () => void;
|
|
9
|
+
}
|
|
10
|
+
declare const GameControls: React.FC<GameControlsProps>;
|
|
11
|
+
export default GameControls;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Component } from 'react';
|
|
2
|
+
import type { InstrumentType, MusicBlocklyConfig, NoteDuration, NoteName, NoteOctave } from './types';
|
|
3
|
+
interface MusicBlocklyContainerProps {
|
|
4
|
+
config: MusicBlocklyConfig;
|
|
5
|
+
onWorkspaceChange: (code: string) => void;
|
|
6
|
+
className?: string;
|
|
7
|
+
onPreloadInstruments?: (instruments: InstrumentType[]) => Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
interface MusicBlocklyContainerState {
|
|
10
|
+
initialized: boolean;
|
|
11
|
+
error: string | null;
|
|
12
|
+
showNoteDialog: boolean;
|
|
13
|
+
noteDialogValues: {
|
|
14
|
+
note: NoteName;
|
|
15
|
+
octave: NoteOctave;
|
|
16
|
+
duration: NoteDuration;
|
|
17
|
+
};
|
|
18
|
+
activeField: any | null;
|
|
19
|
+
}
|
|
20
|
+
declare class MusicBlocklyContainer extends Component<MusicBlocklyContainerProps, MusicBlocklyContainerState> {
|
|
21
|
+
private blocklyDiv;
|
|
22
|
+
private workspace;
|
|
23
|
+
private updateTimeout;
|
|
24
|
+
constructor(props: MusicBlocklyContainerProps);
|
|
25
|
+
componentDidMount(): void;
|
|
26
|
+
componentDidUpdate(prevProps: MusicBlocklyContainerProps): void;
|
|
27
|
+
componentWillUnmount(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Preload common instruments when Blockly container is ready
|
|
30
|
+
*/
|
|
31
|
+
private preloadInstruments;
|
|
32
|
+
private initializeBlockly;
|
|
33
|
+
private generateCode;
|
|
34
|
+
private registerGenerators;
|
|
35
|
+
getWorkspace(): any;
|
|
36
|
+
private handleOpenNoteEditor;
|
|
37
|
+
private handleNoteSave;
|
|
38
|
+
private handleNoteClose;
|
|
39
|
+
render(): JSX.Element;
|
|
40
|
+
}
|
|
41
|
+
export default MusicBlocklyContainer;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type GraphicsConfig, type Note, type Pause } from './types';
|
|
3
|
+
interface MusicCanvasProps {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
notes: (Note | Pause)[];
|
|
7
|
+
currentBeat: number;
|
|
8
|
+
isPlaying: boolean;
|
|
9
|
+
selectedRows: number;
|
|
10
|
+
graphicsConfig: GraphicsConfig;
|
|
11
|
+
editorNotes?: (Note | Pause)[];
|
|
12
|
+
}
|
|
13
|
+
declare const MusicCanvas: React.FC<MusicCanvasProps>;
|
|
14
|
+
export default MusicCanvas;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { MusicBlocklyConfig } from './types';
|
|
3
|
+
interface MusicEditorProps {
|
|
4
|
+
config: MusicBlocklyConfig;
|
|
5
|
+
onWorkspaceChange: (code: string) => void;
|
|
6
|
+
tempo: number;
|
|
7
|
+
onTempoChange: (tempo: number) => void;
|
|
8
|
+
blocklyRef?: React.RefObject<any>;
|
|
9
|
+
}
|
|
10
|
+
declare const MusicEditor: React.FC<MusicEditorProps>;
|
|
11
|
+
export default MusicEditor;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type WithTranslation } from 'react-i18next';
|
|
3
|
+
import { type GraphicsConfig, type MusicConfig, type RunResult } from './types';
|
|
4
|
+
interface MusicGameProps extends WithTranslation {
|
|
5
|
+
className?: string;
|
|
6
|
+
isEditable?: boolean;
|
|
7
|
+
configuration?: MusicConfig;
|
|
8
|
+
onChange?: (config: MusicConfig) => void;
|
|
9
|
+
onRunFinish?: (result: RunResult) => void;
|
|
10
|
+
maxCommands?: number;
|
|
11
|
+
showControls?: boolean;
|
|
12
|
+
graphicsConfig?: Partial<GraphicsConfig>;
|
|
13
|
+
}
|
|
14
|
+
declare const MusicGameWithTranslation: React.ComponentType<Omit<MusicGameProps, keyof WithTranslation>>;
|
|
15
|
+
export default MusicGameWithTranslation;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { GraphicsConfig, InstrumentType, MusicBlocklyConfig, MusicConfig, MusicState, Note, Pause } from './types';
|
|
3
|
+
interface MusicTabsProps {
|
|
4
|
+
musicConfig: MusicConfig;
|
|
5
|
+
gameState: MusicState;
|
|
6
|
+
editorState: MusicState;
|
|
7
|
+
generatedCode: string;
|
|
8
|
+
blocklyConfig: MusicBlocklyConfig;
|
|
9
|
+
onConfigChange: (config: MusicConfig) => void;
|
|
10
|
+
onCodeChange: (code: string) => void;
|
|
11
|
+
onEditorStateChange: (state: Partial<MusicState>) => void;
|
|
12
|
+
onEditorNotesChange?: (notes: (Note | Pause)[]) => void;
|
|
13
|
+
graphicsConfig: GraphicsConfig;
|
|
14
|
+
className?: string;
|
|
15
|
+
blocklyRef?: React.RefObject<any>;
|
|
16
|
+
editorBlocklyRef?: React.RefObject<any>;
|
|
17
|
+
editorNotes?: (Note | Pause)[];
|
|
18
|
+
onPreloadInstruments?: (instruments: InstrumentType[]) => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
declare const MusicTabs: React.FC<MusicTabsProps>;
|
|
21
|
+
export default MusicTabs;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type GraphicsConfig, type InstrumentType, type Note, type Pause } from './types';
|
|
3
|
+
interface MusicVisualEditorProps {
|
|
4
|
+
tempo: number;
|
|
5
|
+
onTempoChange: (tempo: number) => void;
|
|
6
|
+
selectedRows: number;
|
|
7
|
+
onSelectedRowsChange: (rows: number) => void;
|
|
8
|
+
onCodeChange: (code: string) => void;
|
|
9
|
+
onNotesChange?: (notes: (Note | Pause)[]) => void;
|
|
10
|
+
graphicsConfig: GraphicsConfig;
|
|
11
|
+
onPreloadInstruments?: (instruments: InstrumentType[]) => Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
declare const MusicVisualEditor: React.FC<MusicVisualEditorProps>;
|
|
14
|
+
export default MusicVisualEditor;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { NoteDuration, NoteName, NoteOctave } from './types';
|
|
3
|
+
interface NoteDialogProps {
|
|
4
|
+
show: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
onSave: (note: NoteName, octave: NoteOctave, duration: NoteDuration) => void;
|
|
7
|
+
initialValues: {
|
|
8
|
+
note: NoteName;
|
|
9
|
+
octave: NoteOctave;
|
|
10
|
+
duration: NoteDuration;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
declare const NoteDialog: React.FC<NoteDialogProps>;
|
|
14
|
+
export default NoteDialog;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type InstrumentType, type Note, type NoteDuration, type NoteOctave } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Audio engine for playing musical notes using real instrument samples (SoundFont)
|
|
4
|
+
*/
|
|
5
|
+
export declare class AudioEngine {
|
|
6
|
+
private audioContext;
|
|
7
|
+
private masterGain;
|
|
8
|
+
private activeNotes;
|
|
9
|
+
private loadedInstruments;
|
|
10
|
+
private loadingInstruments;
|
|
11
|
+
private readonly instrumentMap;
|
|
12
|
+
constructor();
|
|
13
|
+
private initAudioContext;
|
|
14
|
+
/**
|
|
15
|
+
* Pre-load one or more instruments (public method for proactive loading)
|
|
16
|
+
*/
|
|
17
|
+
preloadInstruments(instrumentTypes: InstrumentType[]): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Load an instrument SoundFont (lazy loading)
|
|
20
|
+
*/
|
|
21
|
+
private loadInstrument;
|
|
22
|
+
/**
|
|
23
|
+
* Play a single note using SoundFont samples
|
|
24
|
+
*/
|
|
25
|
+
playNote(note: Note, tempo: number, instrument?: InstrumentType, onComplete?: () => void): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Convert note name and octave to SoundFont format (e.g., "C4", "D#5")
|
|
28
|
+
*/
|
|
29
|
+
private getNoteNameForSoundfont;
|
|
30
|
+
/**
|
|
31
|
+
* Fallback: Play note using oscillator (for drums or when SoundFont fails)
|
|
32
|
+
*/
|
|
33
|
+
private playNoteWithOscillator;
|
|
34
|
+
/**
|
|
35
|
+
* Configure oscillator and gain based on instrument type with better synthesis
|
|
36
|
+
*/
|
|
37
|
+
private configureInstrument;
|
|
38
|
+
/**
|
|
39
|
+
* Play a keyboard key (for interactive playing)
|
|
40
|
+
*/
|
|
41
|
+
playKeyboardNote(noteName: string, octave: NoteOctave, duration?: NoteDuration, instrument?: InstrumentType): void;
|
|
42
|
+
/**
|
|
43
|
+
* Stop all playing notes
|
|
44
|
+
*/
|
|
45
|
+
stopAll(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Resume audio context (needed for browsers that suspend it)
|
|
48
|
+
*/
|
|
49
|
+
resume(): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Cleanup and close audio context
|
|
52
|
+
*/
|
|
53
|
+
dispose(): void;
|
|
54
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { default as MusicGame } from './MusicGame';
|
|
2
|
+
export { default as MusicCanvas } from './MusicCanvas';
|
|
3
|
+
export { default as MusicEditor } from './MusicEditor';
|
|
4
|
+
export { default as MusicVisualEditor } from './MusicVisualEditor';
|
|
5
|
+
export { default as MusicTabs } from './MusicTabs';
|
|
6
|
+
export { default as GameControls } from './GameControls';
|
|
7
|
+
export { default as MusicBlocklyContainer } from './MusicBlocklyContainer';
|
|
8
|
+
export * from './types';
|
|
9
|
+
export * from './blocks';
|
|
10
|
+
export * from './blockly-messages';
|
|
11
|
+
export * from './graphicsConfig';
|
|
12
|
+
export * from './audioEngine';
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export type NoteDuration = 'whole' | 'half' | 'quarter' | 'eighth' | 'sixteenth';
|
|
2
|
+
export type NoteName = 'C' | 'D' | 'E' | 'F' | 'G' | 'A' | 'B';
|
|
3
|
+
export type NoteOctave = 1 | 2 | 3 | 4 | 5;
|
|
4
|
+
export type InstrumentType = 'piano' | 'guitar' | 'acoustic_guitar' | 'electric_guitar' | 'bass' | 'drums' | 'flute' | 'violin' | 'saxophone';
|
|
5
|
+
export interface Note {
|
|
6
|
+
id: string;
|
|
7
|
+
name: NoteName;
|
|
8
|
+
octave: NoteOctave;
|
|
9
|
+
duration: NoteDuration;
|
|
10
|
+
row: number;
|
|
11
|
+
startBeat: number;
|
|
12
|
+
instrument?: InstrumentType;
|
|
13
|
+
}
|
|
14
|
+
export interface Pause {
|
|
15
|
+
id: string;
|
|
16
|
+
duration: NoteDuration;
|
|
17
|
+
row: number;
|
|
18
|
+
startBeat: number;
|
|
19
|
+
}
|
|
20
|
+
export type MusicCommand = Note | Pause;
|
|
21
|
+
export interface MusicState {
|
|
22
|
+
isPlaying: boolean;
|
|
23
|
+
isPaused: boolean;
|
|
24
|
+
currentBeat: number;
|
|
25
|
+
commands: MusicCommand[];
|
|
26
|
+
commandCount: number;
|
|
27
|
+
maxCommands: number;
|
|
28
|
+
selectedRows: number;
|
|
29
|
+
instrument: InstrumentType;
|
|
30
|
+
tempo: number;
|
|
31
|
+
}
|
|
32
|
+
export interface MusicConfig {
|
|
33
|
+
targetNotes: Note[];
|
|
34
|
+
maxCommands: number;
|
|
35
|
+
selectedRows: number;
|
|
36
|
+
tempo: number;
|
|
37
|
+
instrument: InstrumentType;
|
|
38
|
+
}
|
|
39
|
+
export interface MusicBlocklyConfig {
|
|
40
|
+
allowedTypes: Set<string>;
|
|
41
|
+
limits: Record<string, number>;
|
|
42
|
+
toolbox: string;
|
|
43
|
+
initialXml: string;
|
|
44
|
+
}
|
|
45
|
+
export interface RunResult {
|
|
46
|
+
commands: number;
|
|
47
|
+
reachedTarget: boolean;
|
|
48
|
+
maxCommandsExceeded: boolean;
|
|
49
|
+
notes: Note[];
|
|
50
|
+
executionTime: number;
|
|
51
|
+
accuracy: number;
|
|
52
|
+
comparisonResult?: {
|
|
53
|
+
noteCountMatch: boolean;
|
|
54
|
+
melodyAccuracy: number;
|
|
55
|
+
rhythmAccuracy: number;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export interface GraphicsConfig {
|
|
59
|
+
canvas: {
|
|
60
|
+
backgroundColor: string;
|
|
61
|
+
borderColor: string;
|
|
62
|
+
borderWidth: number;
|
|
63
|
+
};
|
|
64
|
+
staff: {
|
|
65
|
+
lineColor: string;
|
|
66
|
+
lineWidth: number;
|
|
67
|
+
spacing: number;
|
|
68
|
+
};
|
|
69
|
+
notes: {
|
|
70
|
+
fillColor: string;
|
|
71
|
+
strokeColor: string;
|
|
72
|
+
strokeWidth: number;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export declare const DURATION_TO_BEATS: Record<NoteDuration, number>;
|
|
76
|
+
export declare function getNoteFrequency(note: NoteName, octave: NoteOctave): number;
|