Summary and goals
Be-Music Source (BMS) is a file format for rhythm game charts
There are many BMS clients that parse BMS files allowing users to play songs. The current BMS ecosystem runs off sites known as Tables
. These tables are arrays of Chart
objects sorted by difficulty. Chart
objects do not actually contain the chart, they instead contain and MD5 hash of the charts corresponding .bms
file (as well as other metadata like title & author). It is up to the user to source this file & for their client to link the local file to the Chart object.
Sometimes, the metadata sent along with the Chart
object includes a link to a site where the files can be downloaded. Other times, it’s up to the user to hunt down packs or other users who already have the chart.
This app would list all Charts
in a Table
in a easy to navigate web application. With a majority of the data being driven by metadata provided by the table. Admin users are able to create a corresponding object in the apps database against a Chart, where extra metadata can be included, such as download links & descriptions.
Once a corresponding object has been created, even if the chart is no longer in the table; it can still be viewed on the website.
This site will attempt to mirror an osu-esque style of browsing charts:
Scope Breakdown
Deliverables
- An admin panel for managing database objects
- CRUD Tables
- CRUD Charts
- An end user application for viewing database objects
- Read Tables
- Read Charts
Timeline
Technical Breakdown
Personas
- Admin User
- End User
External Integrations
Table Objects
Tables consist of two JSON files served from a URL: A header, and a body.
The header file contains the name of the table and assorted information.
The body file contains all charts in the table as an array.
There is no agreed upon schema in the community for these objects. However, most clients handle some defaults.
interface Header {
// The name of the table
: string;
name// The icon to show in clients (usually unicode shape)
: string;
symbol// URL or Path to the tables body
: string;
data_url// Order levels should be put in in clients, optional?
?: string[];
level_order// What mode (7k/14k/PMS/24k) is the table for, optional?
?: string;
mode }
type TableBody = {
// The title of the song
: string;
title// The songs artist
: string;
artist// MD5 hash used by clients to identify charts
: string;
md5// The charts level
: string;
level// The URL where the chart can be downloaded
?: string;
url// Another URL where the chart can be downloaded (stellabms only?)
?: string;
url_diff// SHA256 of the chart (stellabms only?)
?: string;
sha256// A comment by the uploader. Completely optional.
?: string;
comment }[]
Local Objects
TableMirror Objects
We should store basic metadata about the table to prevent spamming the table host when users view our site. When users view a table we should show extremely slim amounts of information as well as the related localChart
objects in our system. If the user wishes to, they can load the remaining charts we do not have dedicated objects for.
OR
We should store clones of the tables locally to allow users to view the entire tables list of charts in one go. Charts with localChart
data associated will be moved to the top &/ displayed separately.
LocalChart Objects
A more complex object containing metadata about the chart. This could include an image, a brief description, links to more reliable downloads, or even note analysis to generate stats like density/chords. We could also include an array of charts that are similar or considered other difficulties.
Linking
A chart can be in multiple tables, knowing only the chart we should be able to fetch tables its in, and knowing only the table, we should be able to fetch charts.
- Get all charts in table
- Get all tables for chart
If using dynamoDB a linking object would likely have to exist with an index for querying by table identifiers and an index for querying by chart identifiers. Since we expect to be querying this a lot it’s worth making this an index
User activities
Users almost always have read only permissions to all objects.
Admins can read and write
Admin User
- Can manage external tables we fetch from
- Manage
TableMirror
objects - Can create
LocalChart
objects based on table information - Can edit existing
LocalChart
objects - Can delete existing
LocalChart
objects
End User
- Can view
LocalChart
objects related to a table - Can view an external table
- Can view
TableMirror
objects - Can view all
LocalChart
objects paginated by creationDate
User requests
Users will be triggering the bulk of requests in the system
Request system tables
Request system localCharts
Request table charts (non-local)
Implementation timeline
Assuming baseline core starter
- Create admin app
- Create tableMirror object admin CRUD/UI
- Create localChart object admin CRUD/UI
- Create linking object admin CRUD
- Create auto linking function when tables are updated
- Design user table list screen
- Design user chart list screen
- Design user chart view screen
- Create end user app
- Allow end users to browse tables
- Allow end users to browse local charts
- Allow end users to view chart data
Complexities
Things to keep in mind when scoping work out
- Charts can be in multiple tables
- Charts could potentially have many related charts in different tables
- Potentially store hardcoded tables/difficulties against charts to avoid extra queries. Alert admins via UI if their local table data conflicts with the saved data against a chart?
- Table data is inconsistent