Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

COM1003 Java Programming – Semester 2 Assignment

A Spotify Dashboard

Submission deadline 5pm on Tuesday 7 May.

This is an individual assignment. You are not allowed to work in groups and all your code must be your own work. You may not use other peoples’ code or ideas, e.g., taken from the Internet.

Any form of unfair means (plagiarism or collusion) will be treated as a serious academic offence and will be processed under our University Discipline Regulations. These might result in a loss of marks, a possible failure of the module or even expulsion from our University.

For further details, please visit the UG Student Handbook.

Before you begin, you should have completed up to week 6 of the module materials, lab sheets and self-assessment quizzes (for ‘The questions’ and ‘The queries’), and up to week 8 for building the GUI (‘The GUI’ and ‘The custom chart’).

Please post your questions on the Assignment Discussion Board or attend one of the lab sessions where you will have the opportunity to ask questions and show your code to the module leaders or demonstrators. You may ask demonstrators for help in understanding the problem, but this is intended to be an individual assignment, so you should not ask for explicit help with the programming task.

This is a live assignment sheet: you are welcome to add questions or suggestions as comments, which will be addressed by your instructors. Keep an eye out for any highlighted excerpt, as these are corrections/improvements made to the assignment as a result of your comments.

To avoid accidental changes, open this worksheet in Viewing mode unless you want to make a question using a comment:

Please, update the Java version in your build.gradle as follows:

sourceCompatibility = JavaVersion.VERSION_17

targetCompatibility = JavaVersion.VERSION_17

Otherwise you will be programming your assignment in Java 8.

Introduction (link to video brief)

In this assignment, you will build a music dashboard to explore songs, artists, and song characteristics in various music genres. To do this, you will use the material taught in the course: OO programming, the Java Collections Framework, Java Swing and event handling for GUI-building.

Several classes are provided to help you get started to ensure that this assignment is feasible within the time available. You can only change classes you are explicitly asked to create or modify.

Before you begin, read this document carefully. It contains sufficient detail to get you started with the assignment. Read it along with the template project you have been provided. They need to be studied together. The comments provided in the code are written to help you. You are also strongly encouraged to start working on the assignment soon; do not leave it until the last minute.

As in any software project, there is always room for interpretation, and interpreting the assignment handout and developing a solution is part of the work you are expected to do.

Background

Exploring the characteristics of songs to understand what makes a song popular is crucial for artists and music producers to release new albums. In this project, you will:

- Build a dashboard that will allow users to explore the characteristics of music by either song, artist, album, or music properties. You are provided with a modified version of a publicly available dataset. More details are in the section ‘The Dataset.

- Display some details describing the dataset's contents on the console. See the section 'The Questions'.

- Provide the user with the ability to systematically explore and evaluate the music properties of a selection of songs. A list of queries will be provided to your dashboard via a text file. The results shall be displayed on the console. Details about the syntax of queries are in the section ‘The Queries’.

- Provide the user with a GUI that allows interaction with songs, artists, and albums using user-defined filters. You should display the results interactively. The section 'The GUI' details how the GUI will need to operate. The section ‘The Custom Chart’ explains one graphical element in the GUI that will allow the simultaneous comparison of a number of properties.

The Dataset

Your GitHub repository includes the dataset spotify_songs.tsv under src/main/resources. This dataset has been adapted from an open-source Kaggle dataset. Its filename will be provided to your main class (SpotifyDashboardApp.java) as the first argument.  The second argument will be discussed in the section ‘The Queries’.

The data file is plain text and uses the Tab Separated Values file format (TSV).  The first row provides the column header (i.e., property name), and the remaining rows contain the actual values for each of the properties in the dataset (in the same order as the headers). Each of these lines is considered a single song track entry. Song entries do not span multiple lines.

The properties for each song in the dataset are (see TSV file header):

No.

Header

Description

1

track_name

Song name

2

track_artist

Song artist

3

duration_ms

Duration of song in milliseconds

4

track_album_name

Song album name

5

track_popularity

Song popularity (0-100), where higher is more popular

6

danceability

Suitability for dancing (0-1), where higher is more danceable

7

energy

Perceptual measure of intensity and activity (0-1)

8

loudness

Expressed in decibels (dB), typically ranging between -60 and 0

9

speechiness

Presence of spoken words (0-1)

10

acousticness

Confidence measure of track being acoustic (0-1), where higher indicates more acoustic

11

instrumentalness

Confidence measure of track not containing vocals (0-1), where higher indicates more instrumental

12

liveness

Confidence measure if an audience was present in the recording (0-1), where higher indicates more likely to be live

13

valence

Musical positiviness conveyed (0-1), where higher indicates more positive.

14

tempo

Overall estimated tempo in beats per minute (BPM).

Table 1. Description of the properties for each song track entry in the dataset.

Artist/song/album names may be duplicated in multiple song entries. Please, study the class AbstractSongCatalog and its readDataFromFile method.

To verify that your program works, you can use a spreadsheet software (e.g., Excel or Google Sheet). This type of software allows loading TSV files and offers data-filtering features.

Any error in the input data file, no matter how minimal, should stop the execution of the programme as it will not be possible to perform queries or any meaningful GUI interaction. For this, you will need to use exceptions (see the signature of the involved methods).

The Questions

Your program (SpotifyDashboardApp) will be printing to the console some basic details about the dataset. You should print:

- The total number of unique song entries in the dataset.

- The total number of unique artists in the dataset.

- The average duration of a song in the dataset (make this calculation on the unique songs list).

- The average tempo of a song in the dataset (make this calculation on the unique songs list).

- The maximum loudness in the dataset.

- The minimum tempo in the dataset.

When printing numbers to the console, you are encouraged to limit the number of decimals displayed to avoid unnecessary long printouts. This rule also applies to displaying query results and numbers in the GUI.

The class already provides you with some of the template methods that will allow you to answer these questions, check the methods printQuestionAnswers(), printNumberUniqueSongs(), printNumberUniqueArtists(), and printFirstFiveSongEntries(). You will need to work on the class SongCatalog to make them work.

The queries

Your main class (SpotifyDashboardApp) receives as a second argument another filename which will contain a list of individual queries (one per line) of the form:

select songs where popularity > 60

select songs where ENERGY > 0.8 AND DANCEABILITY <= 0.8

In the example above, the first query should produce all songs with a popularity greater than 60. The second query should find songs with energy above 0.8 and danceability below or equal 0.8.

In general, queries will be built as follows:

select songs where [subqueries]

The [subqueries] can have as many and clauses as specified by the user ( not or or clauses are not supported).

For example, to select all song entries with acousticness between 0.5 and 0.7 (0.5 and 0.7 not included) and with popularity between 80 and 100 (inclusive), the user would formulate a slightly more complex query (in a single line):

select songs where acousticness > 0.5 and accousticness < 0.7 and popularity >= 80 and popularity <= 100

The [subqueries] in your queries will be your subqueries and they should support the following comparison operators only for song properties (see class SongProperty) and not song details (see class SongDetail):

Operator

Meaning

Operator

Meaning

>

Larger than

!=

Not equal to

>=

Larger than or equal to

<

Less than

=

Equal to

<=

Less than or equal to

The headers in the datasets indicate the exact syntax to be used in the queries (not case-sensitive). You will need to control for syntactic errors in the provided queries. If anything falls outside the allowed syntax, an IllegalArgumentException should be raised and handled appropriately. You can assume that there will be one query per line in this file, but if during parsing a malformed query is found, the situation should be handled using exceptions, and it should be ignored. The execution of the main programme should not stop. See how the code is set up.

In most cases, your queries will return multiple song entries, and your program will provide informative and easy-to-read outputs to the console for each query.  The selection can range from one song to all the songs in the dataset (an empty selection should be handled gracefully, too).

The methods printNumberQueries() and executeQueries() will report the results after running all the queries in the provided queries file via the console. To make them work, you must work on the classes QueryParser, Query, and SubQuery.

The GUI

Figure 1 shows what the dashboard GUI could look like.  Your template project provides a basic implementation of the main panel containing the four areas highlighted below (see class AbstractSpotifyDashboardPanel).

- Area 1 (top): Allows the user to specify the filters that must be applied to the song entries in the dataset. This includes a filter by artist/album/song and another by property.  Consider using the class SubQuery for the ‘by property filter’. Areas 2, 3 and 4 must refresh whenever the user changes the filter by artist/album/song or clicks the buttons Add by Property Filter or Clear All by Property Filters.

- Area 2 (left): Shows a custom chart that compares the attributes for the current song selection after applying the filters by artist/album/song and by property (Area 1). The class CustomChartPanel will plot a custom chart panel (a hybrid between a circular bar chart and a radar chart). Plots for each chart property's min, max, and average should be shown as an overlay using different colours. You should also add meaningful labels to your custom chart. More details are provided in the section ‘The Custom Chart. You are free to innovate here.

- Area 3 (right-top): Shows basic statistics (maximum, minimum, and average) for the resulting dataset after applying the two sets of filters listed in Area 1. Only numeric attributes are shown in this area (all of them). This area could also display the number of entries shown out of the total number of entries in the full dataset. You are free to innovate here.

- Area 4 (right-bottom): Shows all the details and properties of the song entry selection resulting from applying the two sets of filters listed in Area 1.

Using the JTextArea objects provided in the starting template, achieving a nice tabular look and feel in areas 3 and 4 might be tricky. You could use some tabs, but you are not expected to do much better than what the figure shows. The assessment will consider what is achievable.

Figure 1. GUI screenshot (for reference only). The overlays with the name variables have been added to the screenshot a posteriori to indicate which properties are represented by each axis.

In the example shown in the figure, the user did not select any artist/album/song and specified two filters by property, which were translated into two SubQuery objects representing the subqueries “popularity > 90”, and “energy > 0.6”, respectively.  Every time the user clicked the button Add by Property Filter, a new filter was added to the list of subqueries being shown in the GUI Area 1.  If the user clicks the button Clear All by Property Filters, the List of subqueries needs to be cleared and no by property filters should be applied to the dataset being shown in Areas 2, 3 and 4. This means that the areas 2, 3 and 4 would need to be updated to display the dataset for the selections in the combo boxes labelled “Artist”, “Album”, and “Song”.

The Custom Chart (Area 2)

To understand the characteristics of songs in the dataset, the GUI will allow the user to plot a chart for a selection of the different numeric song attributes available in the dataset. Figure 2 shows how the chart is split into two halves:

- The left half is a circular bar chart that shows counterclockwise the song attributes: popularity, tempo, and loudness.  These attributes are all in 3 different ranges. You will need to find their ranges and normalise these values.

- The right half is a radar chart that shows clockwise the attributes: danceability, energy, speechiness, acousticness, instrumentalness, liveness, and valence. The range of all these attributes is between 0 and 1.

Figure 2. (Left) The Custom chart is split into a circular bar chart and a radar chart. (Right) How song properties are mapped into the custom chart.

See how to build the circular bar chart on the right using the data on the bar chart on the left.

Radar charts, are used in statistics to visualise multivariate data (multiple variables – at least three – at once). Given the data in the table below, a corresponding radar chart could look like the one on the right. Notice that George is the best at solos, Ringo has the best rhythm, and both John and Paul are excellent composers, with John being arguably the funniest one.

Name

Composition

Voice

Rhythm

Solos

Humour

John

10

8

6

5

9

Paul

10

7

6

7

6

George

8

7

6

10

5

Ringo

2

2

10

5

5


The checkboxes ‘Minimum’, ‘Maximum’, and ‘Average’ should display the minimum, maximum, and average values for the song selection, respectively.

Please study the classes CustomChartAxisValues and AbstractCustomChart. They are well-documented and provide guidance on what you need to do. The class CustomChart will extend AbstractCustomChart, and the CustomChartPanel class will create an object of type CustomChart and plot it in the final GUI. You have also been provided with the abstract class AbstractCustomChartPanel that your CustomChartPanel class will need to extend. Your class CustomChartPanel will use Java2D for drawing.  You are expected to draw not only the custom chart but also the axes labels (e.g., in the example above, “Composition”, “Voice”, “Rhythm”, “Solos”, and “Humour” are the labels) and the axes’ values (e.g., in the example above, all axes have the same scale, from 0 to 10, so values are plotted along one single axis).

Scaling of properties when drawing the custom chart:
By the time you start implementing the drawing of the two halves of the custom chart, you will have already seen that different properties come in significantly different value ranges. This means that when drawing your custom chart, the values in each axis will go between the minimum value and the maximum value for each property that the axis displays.

You are not allowed to use any external packages to plot the radar chart.
You are meant to use Java2D exclusively for that.
Those submissions using an external package for this part will be marked as 0.