--- title: BMS Scope of Work updatedAt: 1724302564000 --- - [Summary & Goals](#summary-and-goals) - [Scope Breakdown](#scope-breakdown) - [Deliverables](#deliverables) - [Timeline](#timeline) - [Technical Breakdown](#technical-breakdown) - [Personas](#personas) - [External Integrations](#external-integrations) - [Local Objects](#local-objects) - [User Activities](#user-activities) - [User Requests](#user-requests) # 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](https://osu.ppy.sh) style of browsing charts: - [Example of viewing all charts](https://osu.ppy.sh/beatmapsets) - [Example of viewing specific chart](https://osu.ppy.sh/beatmapsets) # 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 ```mermaid gantt dateFormat YYYY-MM-DD axisFormat %H-%M title BMS Site timeline section Initial Deploy Stand up Baseline Core : a1, 2023-08-01, 1h Deploy dev environment : after a1, 1h Deploy prod environment : a2, after a1, 1h Create public view webapp : a3, after a2, 2h Deploy dev environment : deploy, after a3, 1h Deploy prod environment : after a3, 1h section Chart Object Create Chart object : a4, after deploy, 1h Allow admin to view chart objects : a5, after a4, 1h Allow admin to edit chart objects : after a5, 1h Allow admin to delete chart objects : after a5, 1h section Table integration Create localTable Object : a6, after deploy, 1h Allow admin to configure localTable : a7, after a6, 2h Scheduled job to ping table : a8, after a7, 1h Link charts in system to table : after a8, 2h Clean up dead link objects : after a8, 2h Allow admin to view links : after a8, 2h ``` # 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. ```ts interface Header { // The name of the table name: string; // The icon to show in clients (usually unicode shape) symbol: string; // URL or Path to the tables body data_url: string; // Order levels should be put in in clients, optional? level_order?: string[]; // What mode (7k/14k/PMS/24k) is the table for, optional? mode?: string; } ``` ```ts type TableBody = { // The title of the song title: string; // The songs artist artist: string; // MD5 hash used by clients to identify charts md5: string; // The charts level level: string; // The URL where the chart can be downloaded url?: string; // Another URL where the chart can be downloaded (stellabms only?) url_diff?: string; // SHA256 of the chart (stellabms only?) sha256?: string; // A comment by the uploader. Completely optional. comment?: string; }[] ``` ## 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 ```mermaid sequenceDiagram User->>+API: Request all tables API->>+DynamoDB: Get all tables DynamoDB-->>-API: Return all tables API-->>-User: Return all tables Note right of User: User can browse tables in system ``` ### Request system localCharts ```mermaid sequenceDiagram User->>+API: Request tables charts API->>+DynamoDB: Get local chart objects DynamoDB-->>-API: Return local chart objects API-->>-User: Return charts Note right of User: User can browse charts in system ``` ### Request table charts (non-local) ```mermaid sequenceDiagram User->>+API: Request tables charts API->>+Table: Request table charts Table-->>-API: Return table charts Note right of API: Mutate the returned chart objects Note right of API: Potentially cache this? API-->>-User: Return charts Note right of User: User can view basic chart data ``` ## Implementation timeline Assuming baseline core starter 1. Create admin app 2. Create tableMirror object admin CRUD/UI 3. Create localChart object admin CRUD/UI 4. Create linking object admin CRUD 5. Create auto linking function when tables are updated 6. Design user table list screen 7. Design user chart list screen 8. Design user chart view screen 9. Create end user app 10. Allow end users to browse tables 11. Allow end users to browse local charts 12. 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