diff options
Diffstat (limited to 'src/data/things/flash.js')
-rw-r--r-- | src/data/things/flash.js | 370 |
1 files changed, 295 insertions, 75 deletions
diff --git a/src/data/things/flash.js b/src/data/things/flash.js index 1383fa8..ceed79f 100644 --- a/src/data/things/flash.js +++ b/src/data/things/flash.js @@ -1,25 +1,48 @@ -import Thing from './thing.js'; - -import find from '../../util/find.js'; +export const FLASH_DATA_FILE = 'flashes.yaml'; + +import {input} from '#composite'; +import find from '#find'; +import {empty} from '#sugar'; +import {sortFlashesChronologically} from '#sort'; +import Thing from '#thing'; +import {anyOf, isColor, isContentString, isDirectory, isNumber, isString} + from '#validators'; +import {parseDate, parseContributors} from '#yaml'; + +import {withPropertyFromObject} from '#composite/data'; + +import { + exposeConstant, + exposeDependency, + exposeDependencyOrContinue, + exposeUpdateValueOrContinue, +} from '#composite/control-flow'; + +import { + color, + commentary, + commentatorArtists, + contentString, + contributionList, + directory, + fileExtension, + name, + referenceList, + simpleDate, + urls, + wikiData, +} from '#composite/wiki-properties'; + +import {withFlashAct} from '#composite/things/flash'; +import {withFlashSide} from '#composite/things/flash-act'; export class Flash extends Thing { static [Thing.referenceType] = 'flash'; - static [Thing.getPropertyDescriptors] = ({ - Artist, - Track, - FlashAct, - - validators: { - isDirectory, - isNumber, - isString, - oneOf, - }, - }) => ({ + static [Thing.getPropertyDescriptors] = ({Artist, Track, FlashAct}) => ({ // Update & expose - name: Thing.common.name('Unnamed Flash'), + name: name('Unnamed Flash'), directory: { flags: {update: true, expose: true}, @@ -40,60 +63,77 @@ export class Flash extends Thing { page: { flags: {update: true, expose: true}, - update: {validate: oneOf(isString, isNumber)}, + update: {validate: anyOf(isString, isNumber)}, expose: { transform: (value) => (value === null ? null : value.toString()), }, }, - date: Thing.common.simpleDate(), + color: [ + exposeUpdateValueOrContinue({ + validate: input.value(isColor), + }), - coverArtFileExtension: Thing.common.fileExtension('jpg'), + withFlashAct(), - contributorContribsByRef: Thing.common.contribsByRef(), + withPropertyFromObject({ + object: '#flashAct', + property: input.value('color'), + }), - featuredTracksByRef: Thing.common.referenceList(Track), + exposeDependency({dependency: '#flashAct.color'}), + ], - urls: Thing.common.urls(), + date: simpleDate(), - // Update only + coverArtFileExtension: fileExtension('jpg'), - artistData: Thing.common.wikiData(Artist), - trackData: Thing.common.wikiData(Track), - flashActData: Thing.common.wikiData(FlashAct), + contributorContribs: contributionList(), - // Expose only + featuredTracks: referenceList({ + class: input.value(Track), + find: input.value(find.track), + data: 'trackData', + }), - contributorContribs: Thing.common.dynamicContribs('contributorContribsByRef'), + urls: urls(), - featuredTracks: Thing.common.dynamicThingsFromReferenceList( - 'featuredTracksByRef', - 'trackData', - find.track - ), + commentary: commentary(), - act: { - flags: {expose: true}, + // Update only - expose: { - dependencies: ['flashActData'], + artistData: wikiData({ + class: input.value(Artist), + }), - compute: ({flashActData, [Flash.instance]: flash}) => - flashActData.find((act) => act.flashes.includes(flash)) ?? null, - }, - }, + trackData: wikiData({ + class: input.value(Track), + }), - color: { - flags: {expose: true}, + flashActData: wikiData({ + class: input.value(FlashAct), + }), - expose: { - dependencies: ['flashActData'], + // Expose only - compute: ({flashActData, [Flash.instance]: flash}) => - flashActData.find((act) => act.flashes.includes(flash))?.color ?? null, - }, - }, + commentatorArtists: commentatorArtists(), + + act: [ + withFlashAct(), + exposeDependency({dependency: '#flashAct'}), + ], + + side: [ + withFlashAct(), + + withPropertyFromObject({ + object: '#flashAct', + property: input.value('side'), + }), + + exposeDependency({dependency: '#flashAct.side'}), + ], }); static [Thing.getSerializeDescriptors] = ({ @@ -108,43 +148,223 @@ export class Flash extends Thing { urls: S.id, color: S.id, }); + + static [Thing.findSpecs] = { + flash: { + referenceTypes: ['flash'], + bindTo: 'flashData', + }, + }; + + static [Thing.yamlDocumentSpec] = { + fields: { + 'Flash': {property: 'name'}, + 'Directory': {property: 'directory'}, + 'Page': {property: 'page'}, + 'Color': {property: 'color'}, + 'URLs': {property: 'urls'}, + + 'Date': { + property: 'date', + transform: parseDate, + }, + + 'Cover Art File Extension': {property: 'coverArtFileExtension'}, + + 'Featured Tracks': {property: 'featuredTracks'}, + + 'Contributors': { + property: 'contributorContribs', + transform: parseContributors, + }, + + 'Commentary': {property: 'commentary'}, + + 'Review Points': {ignore: true}, + }, + }; } export class FlashAct extends Thing { - static [Thing.getPropertyDescriptors] = ({ - validators: { - isColor, - }, - }) => ({ + static [Thing.referenceType] = 'flash-act'; + static [Thing.friendlyName] = `Flash Act`; + + static [Thing.getPropertyDescriptors] = () => ({ // Update & expose - name: Thing.common.name('Unnamed Flash Act'), - color: Thing.common.color(), - anchor: Thing.common.simpleString(), - jump: Thing.common.simpleString(), + name: name('Unnamed Flash Act'), + directory: directory(), + color: color(), - jumpColor: { - flags: {update: true, expose: true}, - update: {validate: isColor}, - expose: { - dependencies: ['color'], - transform: (jumpColor, {color}) => - jumpColor ?? color, - } - }, + listTerminology: [ + exposeUpdateValueOrContinue({ + validate: input.value(isContentString), + }), + + withFlashSide(), - flashesByRef: Thing.common.referenceList(Flash), + withPropertyFromObject({ + object: '#flashSide', + property: input.value('listTerminology'), + }), + + exposeDependencyOrContinue({ + dependency: '#flashSide.listTerminology', + }), + + exposeConstant({ + value: input.value(null), + }), + ], + + flashes: referenceList({ + class: input.value(Flash), + find: input.value(find.flash), + data: 'flashData', + }), // Update only - flashData: Thing.common.wikiData(Flash), + flashData: wikiData({ + class: input.value(Flash), + }), + + flashSideData: wikiData({ + class: input.value(FlashSide), + }), // Expose only - flashes: Thing.common.dynamicThingsFromReferenceList( - 'flashesByRef', - 'flashData', - find.flash - ), - }) + side: [ + withFlashSide(), + exposeDependency({dependency: '#flashSide'}), + ], + }); + + static [Thing.findSpecs] = { + flashAct: { + referenceTypes: ['flash-act'], + bindTo: 'flashActData', + }, + }; + + static [Thing.yamlDocumentSpec] = { + fields: { + 'Act': {property: 'name'}, + 'Directory': {property: 'directory'}, + + 'Color': {property: 'color'}, + 'List Terminology': {property: 'listTerminology'}, + + 'Review Points': {ignore: true}, + }, + }; +} + +export class FlashSide extends Thing { + static [Thing.referenceType] = 'flash-side'; + static [Thing.friendlyName] = `Flash Side`; + + static [Thing.getPropertyDescriptors] = () => ({ + // Update & expose + + name: name('Unnamed Flash Side'), + directory: directory(), + color: color(), + listTerminology: contentString(), + + acts: referenceList({ + class: input.value(FlashAct), + find: input.value(find.flashAct), + data: 'flashActData', + }), + + // Update only + + flashActData: wikiData({ + class: input.value(FlashAct), + }), + }); + + static [Thing.yamlDocumentSpec] = { + fields: { + 'Side': {property: 'name'}, + 'Directory': {property: 'directory'}, + 'Color': {property: 'color'}, + 'List Terminology': {property: 'listTerminology'}, + }, + }; + + static [Thing.findSpecs] = { + flashSide: { + referenceTypes: ['flash-side'], + bindTo: 'flashSideData', + }, + }; + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {allInOne}, + thingConstructors: {Flash, FlashAct}, + }) => ({ + title: `Process flashes file`, + file: FLASH_DATA_FILE, + + documentMode: allInOne, + documentThing: document => + ('Side' in document + ? FlashSide + : 'Act' in document + ? FlashAct + : Flash), + + save(results) { + // JavaScript likes you. + + if (!empty(results) && !(results[0] instanceof FlashSide)) { + throw new Error(`Expected a side at top of flash data file`); + } + + let index = 0; + let thing; + for (; thing = results[index]; index++) { + const flashSide = thing; + const flashActRefs = []; + + if (results[index + 1] instanceof Flash) { + throw new Error(`Expected an act to immediately follow a side`); + } + + for ( + index++; + (thing = results[index]) && thing instanceof FlashAct; + index++ + ) { + const flashAct = thing; + const flashRefs = []; + for ( + index++; + (thing = results[index]) && thing instanceof Flash; + index++ + ) { + flashRefs.push(Thing.getReference(thing)); + } + index--; + flashAct.flashes = flashRefs; + flashActRefs.push(Thing.getReference(flashAct)); + } + index--; + flashSide.acts = flashActRefs; + } + + const flashData = results.filter(x => x instanceof Flash); + const flashActData = results.filter(x => x instanceof FlashAct); + const flashSideData = results.filter(x => x instanceof FlashSide); + + return {flashData, flashActData, flashSideData}; + }, + + sort({flashData}) { + sortFlashesChronologically(flashData); + }, + }); } |