Created
February 29, 2024 06:31
-
-
Save ToadKing/5c92191e8e89c1501723da2f318c6e40 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// example input | |
const input = ` | |
Disc 1 | |
Composed by | |
John Doe (1, 2, 6~10) | |
Foo Bar (3) | |
Arranged by | |
Some Guy (1~10) | |
Disc 2 | |
Composed by | |
John Doe (3, 5, 7) | |
Arranged by | |
Foo Bar (1) | |
Baz Qux (2~6) | |
` | |
const parsed = {} | |
let curDisc | |
let curRole | |
for (const rawline of input.split('\n')) { | |
const line = rawline.trim() | |
if (!line) { | |
continue | |
} | |
const newDisc = line.match(/Disc (\d+)$/i) | |
if (newDisc) { | |
curDisc = Number(newDisc[1]) | |
curRole = undefined | |
continue | |
} | |
const newRole = line.match(/^(.*)(?: by|:| by:)$/i) | |
if (newRole) { | |
curRole = newRole[1] | |
continue | |
} | |
const artistsAndTracks = line.match(/^(.*) \(([\d,-~ ]+)\)$/) | |
if (artistsAndTracks) { | |
const [, rawartists, rawtracks] = artistsAndTracks | |
const artists = rawartists.split(',').map(a => a.trim()) | |
const tracks = rawtracks.split(',').map(t => { | |
const range = t.trim().match(/^(\d+)[-~](\d+)$/) | |
if (range) { | |
const [, rawfirst, rawlast] = range | |
const first = Number(rawfirst) | |
const last = Number(rawlast) | |
if (!(last > first)) { | |
throw new RangeError('range not start~end') | |
} | |
const nums = [] | |
for (let i = first; i <= last; i++) { | |
nums.push(i) | |
} | |
return nums | |
} else { | |
const num = Number(t) | |
if (!num) { | |
throw new RangeError(`bad track number: ${t}`) | |
} | |
return [Number(t)] | |
} | |
}).flat().map(t => `${curDisc}.${t}`) | |
if (!parsed[curRole]) { | |
parsed[curRole] = {} | |
} | |
for (const artist of artists) { | |
if (!parsed[curRole][artist]) { | |
parsed[curRole][artist] = new Set() | |
} | |
for (const track of tracks) { | |
parsed[curRole][artist].add(track) | |
} | |
} | |
continue | |
} | |
throw new RangeError(`could not parse line: ${line}`) | |
} | |
for (const [role, artistsAndTracks] of Object.entries(parsed)) { | |
console.log(`${role}:`) | |
for (const [artist, tracks] of Object.entries(artistsAndTracks)) { | |
console.log(`${artist} (${[...tracks].join(', ')})`) | |
} | |
console.log('') | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment