From 60f6591d722d68c365c766699767c9ac94bc9b07 Mon Sep 17 00:00:00 2001 From: Bludwarf Date: Mon, 18 Mar 2024 15:29:54 +0100 Subject: [PATCH] Convertisseur #11 --- README.md | 24 ++--- src/app/als/als-importer.ts | 23 +++-- src/app/convert/convert.component.html | 17 +++- src/app/convert/convert.component.scss | 7 ++ src/app/convert/convert.component.ts | 89 ++++++++++++++++--- .../song/entries/(mod\303\250le).ts.j2" | 40 +++++++++ 6 files changed, 171 insertions(+), 29 deletions(-) create mode 100644 "src/assets/song/entries/(mod\303\250le).ts.j2" diff --git a/README.md b/README.md index 54edcb2..ecef954 100644 --- a/README.md +++ b/README.md @@ -4,25 +4,28 @@ ## Preview mobile -Sur Stackblitz utilliser une largeur de 360px pour avoir un preview assez fidèle d'un affichage mobile d'une largeur de 720px. +Sur Stackblitz utilliser une largeur de 360px pour avoir un preview assez fidèle d'un affichage mobile d'une largeur de +720px. ## Nouveau morceau -Trouver la toute fin du sample dans Ableton Live. Ce sera le `sampleBeatTimeDuration`. +Optionnel : -Exemple si fin à la mesure 92, alors sampleBeatTimeDuration = 92 * 4 +> Trouver la toute fin du sample dans Ableton Live. Ce sera le `sampleBeatTimeDuration`. + +> Exemple si fin à la mesure 92, alors sampleBeatTimeDuration = 92 * 4 Copier le fichier als dans [src/assets/als](src/assets/als). Dézipper manuellement le fichier als et lui ajouter l'extension `.als.xml`. -Utiliser le nom du fichier pour modifier temporairement le test unitaire `should get JSON structure from Petit papillon`. -Ajuster le `sampleBeatTimeDuration` trouvé précédemment. -Lancer le test, puis trouver la conversion JSON dans la console. +> Ajuster le `sampleBeatTimeDuration` trouvé précédemment. + +Uploader le fichier .als.xml dans le [convertisseur](https://bludwarf.github.io/music-diagram-generator/convert). -Copier le contenu dans un fichier json dans le dossier [src/assets/structures](src/assets/structures). +Copier le contenu json dans un fichier json dans le dossier [src/assets/structures](src/assets/structures). -Dupliquer un fichier du dossier [src/app/song/entries](src/app/song/entries). +Copier le contenu ts dans un fichier du dossier [src/app/song/entries](src/app/song/entries). Compléter le fichier [src/app/song/song.component.ts](src/app/song/song.component.ts) : @@ -31,6 +34,5 @@ Compléter le fichier [src/app/song/song.component.ts](src/app/song/song.compone Ajuster le fichier dupliqué : -1. `export default name` -2. `events` -3. `patterns` +1. `events` +2. `patterns` diff --git a/src/app/als/als-importer.ts b/src/app/als/als-importer.ts index f814643..f4a6713 100644 --- a/src/app/als/als-importer.ts +++ b/src/app/als/als-importer.ts @@ -7,12 +7,13 @@ import {AlsProject} from "./v10/als-project"; import {checkXmlContent} from "../xml/xml-js-utils"; -declare function require(name:string): any; // source : https://stackoverflow.com/a/12742371/1655155 - -var convert = require('xml-js') +import * as convert from 'xml-js'; +import {Injectable} from "@angular/core"; +@Injectable({ + providedIn: 'root' +}) // TODO trouver un utilitaire pour dézipper côté client - export class AlsImporter { // async load(file: Blob): Promise { @@ -60,14 +61,22 @@ export class AlsImporter { // }) // } - async loadUnzipped(xmlFile: Blob) { + async loadUnzipped(xmlFile: Blob): Promise { // TODO utiliser plutôt des stream const xmlContent = await xmlFile.text() + return this.loadXmlContent(xmlContent) + } + + loadXmlContent(xmlContent: string): AlsProject { checkXmlContent(xmlContent); - const parsedXml = convert.xml2json(xmlContent, { + const jsonContent = convert.xml2json(xmlContent, { compact: true, }) - return new AlsProject(JSON.parse(parsedXml)) + return this.loadJsonContent(jsonContent) + } + + loadJsonContent(jsonContent: string): AlsProject { + return new AlsProject(JSON.parse(jsonContent)) } } diff --git a/src/app/convert/convert.component.html b/src/app/convert/convert.component.html index a8000d5..fce8975 100644 --- a/src/app/convert/convert.component.html +++ b/src/app/convert/convert.component.html @@ -1,2 +1,17 @@ - + + + + src/assets/als/{{songName}}.als.xml.json : + + + + + src/assets/structures/{{songName}}.json : + + + + + src/app/song/entries/{{songName}}.ts : + + diff --git a/src/app/convert/convert.component.scss b/src/app/convert/convert.component.scss index e69de29..153f7ed 100644 --- a/src/app/convert/convert.component.scss +++ b/src/app/convert/convert.component.scss @@ -0,0 +1,7 @@ +input, textarea { + width: 100vw; +} + +textarea { + resize: vertical; +} diff --git a/src/app/convert/convert.component.ts b/src/app/convert/convert.component.ts index 302fe86..75503e7 100644 --- a/src/app/convert/convert.component.ts +++ b/src/app/convert/convert.component.ts @@ -1,23 +1,36 @@ -import {Component, ElementRef, ViewChild} from '@angular/core'; +import {Component} from '@angular/core'; import convert from "xml-js"; +import {FormsModule} from "@angular/forms"; +import {AlsImporter} from "../als/als-importer"; +import {StructureExtractorFromAls} from "../als/structure-extractor-from-als"; +import {NgIf} from "@angular/common"; + +const songEntryTemplate = '' @Component({ selector: 'app-convert', standalone: true, - imports: [], + imports: [ + FormsModule, + NgIf + ], templateUrl: './convert.component.html', styleUrl: './convert.component.scss' }) export class ConvertComponent { - @ViewChild('textarea') - textArea?: ElementRef + jsonContent?: string + jsonStructure?: string; + songEntry?: string; - async uploadFile(event: Event): Promise { + _songName?: string - if (!this.textArea) { - throw new Error('No textArea') - } + constructor( + private readonly alsImporter: AlsImporter, + ) { + } + + async uploadFile(event: Event): Promise { const element = event.currentTarget as HTMLInputElement; let fileList: FileList | null = element.files; @@ -27,10 +40,66 @@ export class ConvertComponent { const xmlFile = fileList[0] const xmlContent = await xmlFile.text() - const xmlObject = convert.xml2json(xmlContent, { + const jsonContent = convert.xml2json(xmlContent, { compact: true, }) - this.textArea.nativeElement.value = xmlObject + this.jsonContent = jsonContent + + const alsProject = this.alsImporter.loadJsonContent(jsonContent); + const structureExtractor = new StructureExtractorFromAls(alsProject); + this.jsonStructure = JSON.stringify(structureExtractor.toStructureObject(), undefined, 4) + + this.songName = xmlFile.name.substring(0, xmlFile.name.indexOf('.')) + } + + get songName(): string | undefined { + return this._songName + } + + set songName(songName: string) { + this._songName = songName + this.songEntry = ` +import {Key} from "../../notes"; +import stuctureObject from "../../../assets/structures/${songName}.json"; +import {Pattern} from "../../structure/pattern/pattern"; +import {Structure} from "../../structure/structure"; + +const key = Key.Gm +const fretboard = { + lowestFret: 0, + fretsCount: 5, +} + +const couplet = Pattern.fromData({ + key, + name: 'Couplet', + chords: '| A | C | G | F |', + fretboard, +}) + +const refrain = Pattern.fromData({ + key, + name: 'Refrain', + chords: '| A | E | F | G |', + fretboard, +}) + +const ligne1 = [couplet, couplet, refrain,] + +const patterns: Pattern[] = [ + ...ligne1, +] + +const structure = Structure.builder() + .stuctureObject(stuctureObject) + .patterns(patterns) + .build() + +export default { + name: '${songName}', + structure, +} +` } } diff --git "a/src/assets/song/entries/(mod\303\250le).ts.j2" "b/src/assets/song/entries/(mod\303\250le).ts.j2" new file mode 100644 index 0000000..5dd410b --- /dev/null +++ "b/src/assets/song/entries/(mod\303\250le).ts.j2" @@ -0,0 +1,40 @@ +import {Key} from "../../notes"; +import stuctureObject from "../../../assets/structures/{{songName}}.json"; +import {Pattern} from "../../structure/pattern/pattern"; +import {Structure} from "../../structure/structure"; + +const key = Key.Gm +const fretboard = { + lowestFret: 0, + fretsCount: 5, +} + +const couplet = Pattern.fromData({ + key, + name: 'Couplet', + chords: '| A | C | G | F |', + fretboard, +}) + +const refrain = Pattern.fromData({ + key, + name: 'Refrain', + chords: '| A | E | F | G |', + fretboard, +}) + +const ligne1 = [couplet, couplet, refrain,] + +const patterns: Pattern[] = [ + ...ligne1, +] + +const structure = Structure.builder() + .stuctureObject(stuctureObject) + .patterns(patterns) + .build() + +export default { + name: '{{songName}}', + structure, +}