diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml
new file mode 100644
index 0000000..02b915b
--- /dev/null
+++ b/.idea/git_toolbox_prj.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/player.api/assets/seed.cypher b/player.api/assets/seed.cypher
new file mode 100644
index 0000000..fa6ce3b
--- /dev/null
+++ b/player.api/assets/seed.cypher
@@ -0,0 +1,100 @@
+// === MEMBERS ===
+CREATE (:Member {name: "Onye"});
+CREATE (:Member {name: "Eric Westerhold"});
+CREATE (:Member {name: "Andrew Manzaneres"});
+
+// === CORPS ===
+CREATE (:Corps {name: "Bluecoats"});
+CREATE (:Corps {name: "Blue Devils"});
+
+// === SHOWS ===
+CREATE (:Show {title: "To Look For America", year: 2017});
+CREATE (:Show {title: "Kinetic Noise", year: 2015});
+CREATE (:Show {title: "Re:Write of Spring", year: 2013});
+
+// === COMPOSERS ===
+MERGE (ps:Composer {name: "Paul Simon"})
+MERGE (rw:Composer {name: "Rufus Wainwright"})
+MERGE (de:Composer {name: "Duke Ellington"})
+MERGE (is:Composer {name: "Igor Stravinsky"})
+MERGE (sb:Composer {name: "Steven Bryant"})
+MERGE (lc:Composer {name: "Leonard Cohen"})
+MERGE (sr:Composer {name: "Steve Reich"})
+MERGE (ja:Composer {name: "John Adams"})
+MERGE (jan:Composer {name: "John Anderson"})
+MERGE (bi:Composer {name: "Bon Iver"})
+MERGE (mg:Composer {name: "Michael Gordon"})
+MERGE (tb:Composer {name: "The Books"})
+MERGE (uz:Composer {name: "Univers Zero"})
+
+// === PIECES ===
+MERGE (a:Piece {title: "America"})-[:COMPOSED_BY]->(ps)
+MERGE (ag:Piece {title: "Agnus Dei"})-[:COMPOSED_BY]->(rw)
+MERGE (sp:Piece {title: "Spring"})-[:COMPOSED_BY]->(de)
+MERGE (eb:Piece {title: "Ebony Concerto"})-[:COMPOSED_BY]->(is)
+MERGE (cc:Piece {title: "Concerto"})-[:COMPOSED_BY]->(sb)
+MERGE (hl:Piece {title: "Hallelujah"})-[:COMPOSED_BY]->(lc)
+MERGE (cl:Piece {title: "City Life"})-[:COMPOSED_BY]->(sr)
+MERGE (rs:Piece {title: "The Rite of Spring"})-[:COMPOSED_BY]->(is)
+MERGE (sl:Piece {title: "Shaker Loops"})-[:COMPOSED_BY]->(ja)
+MERGE (sl)-[:COMPOSED_BY]->(jan)
+MERGE (ec:Piece {title: "Electric Counterpoint"})-[:COMPOSED_BY]->(sr)
+MERGE (wd:Piece {title: "Woods"})-[:COMPOSED_BY]->(bi)
+MERGE (gt:Piece {title: "Gene Takes A Drink"})-[:COMPOSED_BY]->(mg)
+MERGE (ad:Piece {title: "An Animated Description Of Mr Maps"})-[:COMPOSED_BY]->(tb)
+MERGE (ds:Piece {title: "Dense"})-[:COMPOSED_BY]->(uz);
+
+// === RELATIONSHIPS: Shows → Corps ===
+MATCH (s1:Show {title: "To Look For America"}), (c1:Corps {name: "Bluecoats"})
+CREATE (s1)-[:FIELD_BY]->(c1);
+
+MATCH (s2:Show {title: "Kinetic Noise"}), (c2:Corps {name: "Bluecoats"})
+CREATE (s2)-[:FIELD_BY]->(c2);
+
+MATCH (s3:Show {title: "Re:Write of Spring"}), (c3:Corps {name: "Blue Devils"})
+CREATE (s3)-[:FIELD_BY]->(c3);
+
+// === RELATIONSHIPS: Members → Shows ===
+MATCH (m1:Member {name: "Onye"}), (s1:Show {title: "To Look For America"})
+CREATE (m1)-[:PERFORMED_IN]->(s1);
+
+MATCH (m2:Member {name: "Eric Westerhold"}), (s2:Show {title: "Kinetic Noise"})
+CREATE (m2)-[:PERFORMED_IN]->(s2);
+
+MATCH (m3:Member {name: "Andrew Manzaneres"}), (s3:Show {title: "Re:Write of Spring"})
+CREATE (m3)-[:PERFORMED_IN]->(s3);
+
+// === RELATIONSHIPS: Shows → Pieces ===
+MATCH (s:Show {title: "To Look For America"}),
+ (a:Piece {title: "America"}),
+ (ag:Piece {title: "Agnus Dei"}),
+ (sp:Piece {title: "Spring"}),
+ (eb:Piece {title: "Ebony Concerto"}),
+ (cc:Piece {title: "Concerto"}),
+ (hl:Piece {title: "Hallelujah"}),
+ (cl:Piece {title: "City Life"})
+CREATE (s)-[:FEATURED]->(a),
+ (s)-[:FEATURED]->(ag),
+ (s)-[:FEATURED]->(sp),
+ (s)-[:FEATURED]->(eb),
+ (s)-[:FEATURED]->(cc),
+ (s)-[:FEATURED]->(hl),
+ (s)-[:FEATURED]->(cl);
+
+MATCH (s:Show {title: "Re:Write of Spring"}),
+ (rs:Piece {title: "The Rite of Spring"})
+CREATE (s)-[:FEATURED]->(rs);
+
+MATCH (s:Show {title: "Kinetic Noise"}),
+ (sl:Piece {title: "Shaker Loops"}),
+ (ec:Piece {title: "Electric Counterpoint"}),
+ (wd:Piece {title: "Woods"}),
+ (gt:Piece {title: "Gene Takes A Drink"}),
+ (ad:Piece {title: "An Animated Description Of Mr Maps"}),
+ (ds:Piece {title: "Dense"})
+CREATE (s)-[:FEATURED]->(sl),
+ (s)-[:FEATURED]->(ec),
+ (s)-[:FEATURED]->(wd),
+ (s)-[:FEATURED]->(gt),
+ (s)-[:FEATURED]->(ad),
+ (s)-[:FEATURED]->(ds);
diff --git a/player.api/src/main/java/Scratch.java b/player.api/src/main/java/Scratch.java
new file mode 100644
index 0000000..5f9ee8a
--- /dev/null
+++ b/player.api/src/main/java/Scratch.java
@@ -0,0 +1,29 @@
+import com.dci.aaronic.player.io.DCIFileMetadataContainer;
+import com.dci.aaronic.player.io.DCIFileWriter;
+
+import java.io.File;
+import java.io.IOException;
+
+public class Scratch {
+
+ public static void main(String[] args) {
+ File test_file = new File("C:\\Users\\kacar\\Desktop\\Data Projects\\DCIPlayer\\player.api\\player.api\\assets\\Bluecoats_2015_Kinetic_Noise.mp4");
+ DCIFileMetadataContainer metadata = null;
+ try {
+ metadata = DCIFileMetadataContainer.extract(test_file.getName());
+
+ System.out.println(metadata);
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ try {
+ File testOut = new File("C:\\Users\\kacar\\Desktop\\Data Projects\\DCIPlayer\\player.api\\player.api\\assets\\Bluecoats_2015_Kinetic_Noise.dci");
+ DCIFileWriter writer = new DCIFileWriter();
+ writer.write(test_file, metadata, testOut);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/api/Application.java b/player.api/src/main/java/com/dci/aaronic/player/api/Application.java
new file mode 100644
index 0000000..259387e
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/api/Application.java
@@ -0,0 +1,13 @@
+package com.dci.aaronic.player.api;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileMetadataContainer.java b/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileMetadataContainer.java
new file mode 100644
index 0000000..93cdf4d
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileMetadataContainer.java
@@ -0,0 +1,91 @@
+package com.dci.aaronic.player.io;
+
+import com.dci.aaronic.player.models.Corps;
+import com.dci.aaronic.player.utils.Utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class DCIFileMetadataContainer {
+ public int year;
+ public String title;
+ public String corps;
+
+ public DCIFileMetadataContainer() {}
+
+ public DCIFileMetadataContainer(int year, String title, String corps) {
+ this.year = year;
+ this.title = title;
+ this.corps = corps;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getCorps() {
+ return corps;
+ }
+
+ public void setCorps(String corps) {
+ this.corps = corps;
+ }
+
+ public static DCIFileMetadataContainer extract(String fileName) throws IOException {
+ Pattern yearPattern = Pattern.compile("\\d{4}");
+ Matcher yearMatcher = yearPattern.matcher(fileName);
+ String year = null;
+ if (yearMatcher.find()) {
+ year = yearMatcher.group();
+ }
+ String foundCorps = null;
+ for (Corps corps: Utils.ALL_CORPS) {
+ if (fileName.contains(corps.getName())) {
+ foundCorps = corps.getName();
+ break;
+ }
+ }
+
+ String fileExtension = fileName.substring(fileName.lastIndexOf("."));
+
+ String title = fileName;
+ if (foundCorps != null) {
+ title = title.replace(foundCorps, "");
+ }
+
+ if (year != null) {
+ title = title.replace(year, "");
+ }
+
+ if (fileExtension != null) {
+ title = title.replace(fileExtension, "");
+ }
+
+ title = title.replace("_", " ");
+ title = title.trim();
+ return new DCIFileMetadataContainer(Integer.parseInt(year), title, foundCorps);
+ }
+
+ public String toString() {
+ return "DCIFileMetadataContainer{" +
+ "year=" + year +
+ ", title='" + title + '\'' +
+ ", corps='" + corps + '\'' +
+ '}';
+ }
+
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileMetadataSerializer.java b/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileMetadataSerializer.java
new file mode 100644
index 0000000..1c2fa66
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileMetadataSerializer.java
@@ -0,0 +1,28 @@
+package com.dci.aaronic.player.io;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+
+public class DCIFileMetadataSerializer {
+
+ private static final ObjectMapper objectMapper = new ObjectMapper();
+
+ public static byte[] serialize(DCIFileMetadataContainer metadata) throws IOException {
+ try {
+ return objectMapper.writeValueAsBytes(metadata);
+ }
+ catch (IOException e) {
+ throw new IOException("Error serializing metadata: " + e);
+ }
+ }
+
+ public static DCIFileMetadataContainer deserialize(byte[] bytes) throws IOException {
+ try {
+ return objectMapper.readValue(bytes, DCIFileMetadataContainer.class);
+ }
+ catch (IOException e) {
+ throw new IOException("Error deserializing metadata: " + e);
+ }
+ }
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileReader.java b/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileReader.java
new file mode 100644
index 0000000..d426b34
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileReader.java
@@ -0,0 +1,36 @@
+package com.dci.aaronic.player.io;
+
+import java.io.*;
+import java.util.Arrays;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class DCIFileReader {
+
+ private static final byte[] MAGIC = ".DCI".getBytes();
+ private final ObjectMapper objectMapper = new ObjectMapper();
+
+ public void read(File file) throws IOException{
+ try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
+ byte[] magic = new byte[MAGIC.length];
+ in.readFully(magic);
+ if (!Arrays.equals(magic, MAGIC)) {
+ throw new IOException("Header mismatch - not a valid .DCI file");
+ }
+ int version = in.readInt();
+ if (version != 1) {
+ throw new IOException("Unsupported version: " + version);
+ }
+ int metaLength = in.readInt();
+ byte[] meta = new byte[metaLength];
+ in.readFully(meta);
+ Map metaMap = objectMapper.readValue(meta, Map.class); // <1>
+
+ System.out.println(metaMap);
+
+ byte[] content = in.readAllBytes();
+ }
+
+ }
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileWriter.java b/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileWriter.java
new file mode 100644
index 0000000..f46d22f
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/io/DCIFileWriter.java
@@ -0,0 +1,28 @@
+package com.dci.aaronic.player.io;
+
+import jdk.jshell.spi.ExecutionControl;
+
+import java.io.*;
+import java.nio.file.Files;
+
+//Convert MP4 to DCI
+
+public class DCIFileWriter {
+
+ private static final byte[] MAGIC = ".DCI".getBytes();
+
+ public void write(File file, DCIFileMetadataContainer metadata, File outputFile) throws IOException {
+ byte[] content = Files.readAllBytes(file.toPath());
+ try (DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile))) {
+ out.write(MAGIC);
+ out.writeInt(1);
+ byte[] meta = DCIFileMetadataSerializer.serialize(metadata);
+ out.writeInt(meta.length);
+ out.write(meta);
+ out.write(content);
+ }
+ catch (IOException e) {
+ System.out.println("Error creating DCI file: " + e);
+ }
+ }
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/models/Corps.java b/player.api/src/main/java/com/dci/aaronic/player/models/Corps.java
new file mode 100644
index 0000000..8e0aad0
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/models/Corps.java
@@ -0,0 +1,22 @@
+package com.dci.aaronic.player.models;
+
+public class Corps {
+ public String name;
+ public int foundingYear;
+ public String homeCity;
+ public String homeState;
+ public String[] aliases;
+
+
+ public Corps(String name, int foundingYear, String homeCity, String homeState, String[] aliases) {
+ this.name = name;
+ this.foundingYear = foundingYear;
+ this.homeCity = homeCity;
+ this.homeState = homeState;
+ this.aliases = aliases;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/models/CorpsProgram.java b/player.api/src/main/java/com/dci/aaronic/player/models/CorpsProgram.java
new file mode 100644
index 0000000..c3477dc
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/models/CorpsProgram.java
@@ -0,0 +1,8 @@
+package com.dci.aaronic.player.models;
+
+public class CorpsProgram {
+
+ private Corps _corps;
+ private MusicSelection[] _reportoires;
+ private int _year;
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/models/CorpsStaff.java b/player.api/src/main/java/com/dci/aaronic/player/models/CorpsStaff.java
new file mode 100644
index 0000000..69965b0
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/models/CorpsStaff.java
@@ -0,0 +1,10 @@
+package com.dci.aaronic.player.models;
+
+public class CorpsStaff {
+
+ public Member President;
+ public Member BrassCaptionHead;
+ public Member PercussionCaptionHead;
+ public Member VisualCaptionHead;
+
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/models/Member.java b/player.api/src/main/java/com/dci/aaronic/player/models/Member.java
new file mode 100644
index 0000000..942e093
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/models/Member.java
@@ -0,0 +1,4 @@
+package com.dci.aaronic.player.models;
+
+public class Member {
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/models/MusicSelection.java b/player.api/src/main/java/com/dci/aaronic/player/models/MusicSelection.java
new file mode 100644
index 0000000..fcad4dd
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/models/MusicSelection.java
@@ -0,0 +1,9 @@
+package com.dci.aaronic.player.models;
+
+public class MusicSelection {
+
+ public String title;
+ public String subtitle;
+ public String composer;
+
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/models/Section.java b/player.api/src/main/java/com/dci/aaronic/player/models/Section.java
new file mode 100644
index 0000000..d11b01f
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/models/Section.java
@@ -0,0 +1,31 @@
+package com.dci.aaronic.player.models;
+
+public enum Section {
+ BRASS,
+ PERCUSSION,
+ COLORGUARD;
+
+ public enum Subsection {
+ TRUMPETS(BRASS),
+ MELLOPHONES(BRASS),
+ BARITONES(BRASS),
+ CONTRAS(BRASS),
+ SNARES(PERCUSSION),
+ TENORS(PERCUSSION),
+ BASSES(PERCUSSION),
+ CYMBALS(PERCUSSION),
+ FRONTENSEMBLE(PERCUSSION),
+ FLAGS(COLORGUARD),
+ RIFLESANDSABRES(COLORGUARD);
+
+ private final Section _section;
+
+ Subsection(Section section) {
+ _section = section;
+ }
+
+ public Section getSection() {
+ return _section;
+ }
+ }
+}
diff --git a/player.api/src/main/java/com/dci/aaronic/player/utils/Utils.java b/player.api/src/main/java/com/dci/aaronic/player/utils/Utils.java
new file mode 100644
index 0000000..8297ce4
--- /dev/null
+++ b/player.api/src/main/java/com/dci/aaronic/player/utils/Utils.java
@@ -0,0 +1,19 @@
+package com.dci.aaronic.player.utils;
+
+import com.dci.aaronic.player.models.Corps;
+
+import java.util.List;
+
+public class Utils {
+
+ private Utils() {}
+
+ public static List ALL_CORPS = List.of(
+ new Corps("Bluecoats", 1974, "Canton", "Ohio",
+ new String[]{
+ "Bluecoats",
+ "Bloo"
+ })
+ );
+
+}
diff --git a/player.api/src/test/java/com/dci/aaronic/player/api/ApplicationTests.java b/player.api/src/test/java/com/dci/aaronic/player/api/ApplicationTests.java
new file mode 100644
index 0000000..a939ba0
--- /dev/null
+++ b/player.api/src/test/java/com/dci/aaronic/player/api/ApplicationTests.java
@@ -0,0 +1,13 @@
+package com.dci.aaronic.player.api;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}