Initial commit

This commit is contained in:
P 2025-01-31 14:15:48 +01:00
commit d521001dd4
18 changed files with 2282 additions and 0 deletions

73
build.xml Normal file
View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="Playlist" default="default" basedir=".">
<description>Builds, tests, and runs the project Playlist.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar: JAR building
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="Playlist-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

View File

@ -0,0 +1,4 @@
#Fri, 31 Jan 2025 01:21:27 +0100
/home/blackilykat/NetbeansProjects/school/Playlist=

BIN
build/classes/Artista.class Normal file

Binary file not shown.

BIN
build/classes/Brano.class Normal file

Binary file not shown.

BIN
build/classes/Main.class Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

3
manifest.mf Normal file
View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

1771
nbproject/build-impl.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
build.xml.data.CRC32=e8bcf82c
build.xml.script.CRC32=63f50820
build.xml.stylesheet.CRC32=f85dc8f2@1.111.0.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=e8bcf82c
nbproject/build-impl.xml.script.CRC32=f108b4e2
nbproject/build-impl.xml.stylesheet.CRC32=12e0a6c2@1.111.0.48

View File

@ -0,0 +1,2 @@
compile.on.save=true
user.properties.file=/home/blackilykat/.netbeans/dev/build.properties

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/home/blackilykat/NetbeansProjects/school/Playlist/src/Playlist.java</file>
<file>file:/home/blackilykat/NetbeansProjects/school/Playlist/src/Brano.java</file>
<file>file:/home/blackilykat/NetbeansProjects/school/Playlist/src/Main.java</file>
<file>file:/home/blackilykat/NetbeansProjects/school/Playlist/src/Artista.java</file>
</group>
</open-files>
</project-private>

View File

@ -0,0 +1,95 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processor.options=
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.modulepath=\
${run.modulepath}
debug.test.classpath=\
${run.test.classpath}
debug.test.modulepath=\
${run.test.modulepath}
# Files in build.classes.dir which should be excluded from distribution jar
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/Playlist.jar
dist.javadoc.dir=${dist.dir}/javadoc
dist.jlink.dir=${dist.dir}/jlink
dist.jlink.output=${dist.jlink.dir}/Playlist
excludes=
includes=**
jar.compress=false
javac.classpath=
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.external.vm=true
javac.modulepath=
javac.processormodulepath=
javac.processorpath=\
${javac.classpath}
javac.source=23
javac.target=23
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}
javac.test.modulepath=\
${javac.modulepath}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.html5=false
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
# The jlink additional root modules to resolve
jlink.additionalmodules=
# The jlink additional command line parameters
jlink.additionalparam=
jlink.launcher=true
jlink.launcher.name=Playlist
main.class=Main
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.modulepath=\
${javac.modulepath}
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
run.test.modulepath=\
${javac.test.modulepath}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

15
nbproject/project.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>Playlist</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

17
src/Artista.java Normal file
View File

@ -0,0 +1,17 @@
public class Artista {
public final String nome;
public final int annoNascita;
public final String nazionalita;
public Artista(String nome, int annoNascita, String nazionalita) {
this.nome = nome;
this.annoNascita = annoNascita;
this.nazionalita = nazionalita;
}
@Override
public String toString() {
// anno di nascita negativo se non si sa
return annoNascita < 0 ? String.format("%s (%s)", nome, nazionalita) : String.format("%s (%d, %s)", nome, annoNascita, nazionalita);
}
}

40
src/Brano.java Normal file
View File

@ -0,0 +1,40 @@
import java.util.Arrays;
public class Brano {
public final String titolo;
public final String genere;
// Durata in secondi
public final int durata;
public final Artista[] artisti;
public Brano(String titolo, String genere, int minuti, int secondi, Artista... artisti) {
this(titolo, genere, minuti * 60 + secondi, artisti);
}
public Brano(String titolo, String genere, int durata, Artista... artisti) {
if(artisti.length > 5) {
throw new IllegalArgumentException("Un brano non può avere più di 5 artisti");
}
if(durata < 0) {
throw new IllegalArgumentException("Un brano non può avere durata negativa");
}
this.titolo = titolo;
this.genere = genere;
this.durata = durata;
this.artisti = artisti;
}
@Override
public String toString() {
return String.format(
"(%s, %d:%02d) \"%s\" - %s",
genere,
durata / 60,
durata % 60,
titolo,
String.join(", ", Arrays.stream(artisti).map(artista -> artista.toString()).toList())
);
}
}

95
src/Main.java Normal file
View File

@ -0,0 +1,95 @@
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SpringLayout;
import java.awt.Container;
import java.awt.Dimension;
public class Main {
public static void main(String[] args) {
Artista ivycomb = new Artista("ivycomb", 2000, "Canada");
Artista stephanafro = new Artista("Stephanafro", -1, "USA");
Brano pennyPinched = new Brano("Penny Pinched", "pop", 2, 15, ivycomb, stephanafro);
Brano vancouver = new Brano("Vancouver", "pop", 3, 42, ivycomb, stephanafro);
Brano terminal18 = new Brano("Terminal 18", "pop", 3, 49, ivycomb, stephanafro);
Playlist playlist = new Playlist(pennyPinched, vancouver, terminal18);
Artista caparezza = new Artista("Caparezza", 1973, "Italia");
Artista diegoPerrone = new Artista("Diego Perrone", 1975, "Italia");
Brano faiDaTela = new Brano("Fai Da Tela", "hip hop", 3, 59, caparezza, diegoPerrone);
Brano micaVanGogh = new Brano("Mica Van Gogh", "hip hop", 3, 55, caparezza);
Brano nonMeLoPossoPermettere = new Brano("Non me lo posso permettere", "hip hop", 3, 46, caparezza);
playlist.aggiungiInCoda(faiDaTela);
playlist.aggiungiInCoda(micaVanGogh);
playlist.aggiungiInCoda(nonMeLoPossoPermettere);
JFrame frame = new JFrame("Playlist");
frame.setSize(new Dimension(500, 250));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SpringLayout layout = new SpringLayout();
frame.setLayout(layout);
JLabel testoBranoCorrente = new JLabel(playlist.corrente().toString());
frame.add(testoBranoCorrente);
JButton bottoneProssimo = new JButton("Prossimo");
bottoneProssimo.addActionListener(e -> {
if(e.getSource() != bottoneProssimo) return;
Brano nuovoBrano = playlist.prossimo();
if(nuovoBrano != null) {
testoBranoCorrente.setText(nuovoBrano.toString());
}
});
frame.add(bottoneProssimo);
JButton bottonePrecedente = new JButton("Precedente");
bottonePrecedente.addActionListener(e -> {
if(e.getSource() != bottonePrecedente) return;
Brano nuovoBrano = playlist.precedente();
if(nuovoBrano != null) {
testoBranoCorrente.setText(nuovoBrano.toString());
}
});
frame.add(bottonePrecedente);
JCheckBox opzioneShuffle = new JCheckBox("Shuffle");
opzioneShuffle.addActionListener(e -> {
if(e.getSource() != opzioneShuffle) return;
playlist.shuffle(opzioneShuffle.isSelected());
});
frame.add(opzioneShuffle);
JCheckBox opzioneRepeat = new JCheckBox("Repeat");
opzioneRepeat.addActionListener(e -> {
if(e.getSource() != opzioneRepeat) return;
playlist.repeat(opzioneRepeat.isSelected());
});
frame.add(opzioneRepeat);
Container contentPane = frame.getContentPane();
layout.putConstraint(SpringLayout.NORTH, testoBranoCorrente, 50, SpringLayout.NORTH, contentPane);
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, testoBranoCorrente, 0, SpringLayout.HORIZONTAL_CENTER, contentPane);
layout.putConstraint(SpringLayout.NORTH, bottonePrecedente, 20, SpringLayout.SOUTH, testoBranoCorrente);
layout.putConstraint(SpringLayout.EAST, bottonePrecedente, 0, SpringLayout.HORIZONTAL_CENTER, contentPane);
layout.putConstraint(SpringLayout.NORTH, bottoneProssimo, 0, SpringLayout.NORTH, bottonePrecedente);
layout.putConstraint(SpringLayout.WEST, bottoneProssimo, 0, SpringLayout.EAST, bottonePrecedente);
layout.putConstraint(SpringLayout.NORTH, opzioneRepeat, 10, SpringLayout.SOUTH, bottonePrecedente);
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, opzioneRepeat, 0, SpringLayout.HORIZONTAL_CENTER, contentPane);
layout.putConstraint(SpringLayout.NORTH, opzioneShuffle, 10, SpringLayout.SOUTH, opzioneRepeat);
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, opzioneShuffle, 0, SpringLayout.HORIZONTAL_CENTER, contentPane);
frame.setVisible(true);
}
}

147
src/Playlist.java Normal file
View File

@ -0,0 +1,147 @@
import java.util.Random;
public class Playlist {
private Nodo<Brano> corrente = null;
private Nodo<Brano> testa = null;
private Nodo<Brano> coda = null;
private boolean shuffle = false;
private Random random = null;
private Nodo<Nodo<Brano>> pilaPrecedenti = null;
private Nodo<Nodo<Brano>> pilaProssimi = null;
private int dimensione = 0;
public Playlist(Brano... brani) {
for(Brano brano : brani) {
if(brano == null) continue;
aggiungiInCoda(brano);
}
}
public void aggiungiInCoda(Brano brano) {
dimensione++;
if(corrente != null) {
Nodo<Brano> cursore = corrente;
while(cursore.prossimo != null) cursore = cursore.prossimo;
cursore.prossimo = new Nodo<Brano>(brano);
cursore.prossimo.precedente = cursore;
coda = cursore.prossimo;
} else {
corrente = new Nodo<Brano>(brano);
testa = corrente;
coda = corrente;
}
}
private Nodo<Brano> branoCasuale() {
Nodo<Brano> cursore = testa;
if(random == null) random = new Random();
int pos = random.nextInt(0, dimensione);
for(int i = 0; i < pos; i++) {
cursore = cursore.prossimo;
}
return cursore;
}
public Brano precedente() {
if(dimensione == 0) return null;
if(pilaPrecedenti != null) {
aggiungiInProssimi(corrente);
corrente = pilaPrecedenti.valore;
pilaPrecedenti = pilaPrecedenti.prossimo;
if(pilaPrecedenti != null) {
pilaPrecedenti.precedente = null;
}
return corrente.valore;
}
if(shuffle) {
aggiungiInProssimi(corrente);
corrente = branoCasuale();
return corrente.valore;
}
if(corrente == null || corrente.precedente == null) return null;
aggiungiInProssimi(corrente);
corrente = corrente.precedente;
return corrente.valore;
}
private void aggiungiInProssimi(Nodo<Brano> nodo) {
Nodo<Nodo<Brano>> nuovoProssimo = new Nodo<Nodo<Brano>>(nodo);
if(pilaProssimi != null) {
nuovoProssimo.prossimo = pilaProssimi;
nuovoProssimo.prossimo.precedente = nuovoProssimo;
}
pilaProssimi = nuovoProssimo;
}
public Brano corrente() {
if(corrente == null) return null;
return corrente.valore;
}
public Brano prossimo() {
if(dimensione == 0) return null;
if(pilaProssimi != null) {
aggiungiInPrecedenti(corrente);
corrente = pilaProssimi.valore;
pilaProssimi = pilaProssimi.prossimo;
if(pilaProssimi != null) {
pilaProssimi.precedente = null;
}
return corrente.valore;
}
if(shuffle) {
aggiungiInPrecedenti(corrente);
corrente = branoCasuale();
return corrente.valore;
}
if(corrente == null || corrente.prossimo == null) return null;
aggiungiInPrecedenti(corrente);
corrente = corrente.prossimo;
return corrente.valore;
}
private void aggiungiInPrecedenti(Nodo<Brano> nodo) {
Nodo<Nodo<Brano>> nuovoPrecedente = new Nodo<Nodo<Brano>>(corrente);
if(pilaPrecedenti != null) {
nuovoPrecedente.prossimo = pilaPrecedenti;
nuovoPrecedente.prossimo.precedente = nuovoPrecedente;
}
pilaPrecedenti = nuovoPrecedente;
}
public void repeat(boolean abilitato) {
// In un contesto reale non modificherei la lista in se ma cambierei la logica solo
// quando devo selezionare la traccia successiva o precedente. Per scopi didattici,
// rendo la lista una lista circolare.
if(abilitato) {
testa.precedente = coda;
coda.prossimo = testa;
} else {
testa.precedente = null;
coda.prossimo = null;
}
System.out.println("Repeat: " + abilitato);
}
public void shuffle(boolean abilitato) {
shuffle = abilitato;
System.out.println("Shuffle: " + abilitato);
}
private class Nodo<T> {
public T valore;
public Nodo<T> prossimo;
public Nodo<T> precedente;
public Nodo(T valore) {
this.valore = valore;
}
}
}