Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions SiteApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
FEB722BE2E776336006A4DA2 /* Algorithms in Frameworks */ = {isa = PBXBuildFile; productRef = FEB722BD2E776336006A4DA2 /* Algorithms */; };
FED94E0A2F1D481100E7A555 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = FED94E092F1D481100E7A555 /* ArgumentParser */; };
FED95A502F1D7A9C00E7A555 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = FED95A4F2F1D7A9C00E7A555 /* Collections */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -83,6 +84,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FED95A502F1D7A9C00E7A555 /* Collections in Frameworks */,
FED94E0A2F1D481100E7A555 /* ArgumentParser in Frameworks */,
FEB722BE2E776336006A4DA2 /* Algorithms in Frameworks */,
);
Expand Down Expand Up @@ -148,6 +150,7 @@
packageProductDependencies = (
FEB722BD2E776336006A4DA2 /* Algorithms */,
FED94E092F1D481100E7A555 /* ArgumentParser */,
FED95A4F2F1D7A9C00E7A555 /* Collections */,
);
productName = SiteApp;
productReference = FE5360FD29CE82CA00618099 /* SiteApp.app */;
Expand Down Expand Up @@ -207,6 +210,7 @@
packageReferences = (
FEB4895C2E6E6E8F0043057D /* XCRemoteSwiftPackageReference "swift-argument-parser" */,
FEB722BC2E776336006A4DA2 /* XCRemoteSwiftPackageReference "swift-algorithms" */,
FED95A4E2F1D7A9C00E7A555 /* XCRemoteSwiftPackageReference "swift-collections" */,
);
productRefGroup = FE5360FE29CE82CA00618099 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -586,6 +590,14 @@
version = 1.2.1;
};
};
FED95A4E2F1D7A9C00E7A555 /* XCRemoteSwiftPackageReference "swift-collections" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/apple/swift-collections.git";
requirement = {
kind = exactVersion;
version = 1.3.0;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
Expand All @@ -599,6 +611,11 @@
package = FEB4895C2E6E6E8F0043057D /* XCRemoteSwiftPackageReference "swift-argument-parser" */;
productName = ArgumentParser;
};
FED95A4F2F1D7A9C00E7A555 /* Collections */ = {
isa = XCSwiftPackageProductDependency;
package = FED95A4E2F1D7A9C00E7A555 /* XCRemoteSwiftPackageReference "swift-collections" */;
productName = Collections;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = FE5360F529CE82CA00618099 /* Project object */;
Expand Down
40 changes: 15 additions & 25 deletions Sources/MusicData/Bracket.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,36 +35,26 @@ struct Bracket: Codable, Sendable {
let artistFirstSetsMap: [Artist.ID: FirstSet]
let venueFirstSetsMap: [Venue.ID: FirstSet]

public init(music: Music) async {
init(music: Music) async {
var signpost = Signpost(category: "bracket", name: "process")
signpost.start()

async let librarySortTokenMap = music.librarySortTokenMap
async let artistRanks = music.artistRankings
async let venueRanks = music.venueRankings
async let artistSpanRanks = music.artistSpanRankings
async let venueSpanRanks = music.venueSpanRankings
async let artistVenueRanks = music.artistVenueRankings
async let venueArtistRanks = music.venueArtistRankings
async let annumShowRanks = music.annumShowRankings
async let annumVenueRanks = music.annumVenueRankings
async let annumArtistRanks = music.annumArtistRankings
async let decades = music.decadesMap
async let artistFirsts = music.artistFirstSets
async let venueFirsts = music.venueFirstSets
async let tracker = music.tracker

self.artistRankingMap = await tracker.artistRankings()
self.venueRankingMap = await tracker.venueRankings()
self.artistShowSpanRankingMap = await tracker.artistSpanRankings()
self.venueShowSpanRankingMap = await tracker.venueSpanRankings()
self.artistVenueRankingMap = await tracker.artistVenueRankings()
self.venueArtistRankingMap = await tracker.venueArtistRankings()
self.annumShowRankingMap = await tracker.annumShowRankings()
self.annumVenueRankingMap = await tracker.annumVenueRankings()
self.annumArtistRankingMap = await tracker.annumArtistRankings()
self.decadesMap = await tracker.decadesMap()
self.artistFirstSetsMap = await tracker.artistFirstSets()
self.venueFirstSetsMap = await tracker.venueFirstSets()

self.librarySortTokenMap = await librarySortTokenMap
self.artistRankingMap = await artistRanks
self.venueRankingMap = await venueRanks
self.artistShowSpanRankingMap = await artistSpanRanks
self.venueShowSpanRankingMap = await venueSpanRanks
self.artistVenueRankingMap = await artistVenueRanks
self.venueArtistRankingMap = await venueArtistRanks
self.annumShowRankingMap = await annumShowRanks
self.annumVenueRankingMap = await annumVenueRanks
self.annumArtistRankingMap = await annumArtistRanks
self.decadesMap = await decades
self.artistFirstSetsMap = await artistFirsts
self.venueFirstSetsMap = await venueFirsts
}
}
168 changes: 2 additions & 166 deletions Sources/MusicData/Music+Ranking.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,173 +7,9 @@

import Foundation

extension Collection where Element == Show {
fileprivate func dates(withArtist id: Artist.ID) -> Set<PartialDate> {
reduce(into: Set<PartialDate>()) {
guard $1.artists.contains(id) else { return }
$0.insert($1.date)
}
}

fileprivate func dates(withVenue id: Venue.ID) -> Set<PartialDate> {
reduce(into: Set<PartialDate>()) {
guard $1.venue == id else { return }
$0.insert($1.date)
}
}

fileprivate func venues(withArtist id: Artist.ID) -> [Venue.ID] {
self.compactMap {
guard $0.artists.contains(id) else { return nil }
return $0.venue
}
}

fileprivate func artists(withVenue id: Venue.ID) -> [Artist.ID] {
self.flatMap {
guard $0.venue == id else { return [Artist.ID]() }
return $0.artists
}
}

fileprivate func artists(annum: Annum) -> [Artist.ID] {
self.flatMap {
guard $0.date.annum == annum else { return [Artist.ID]() }
return $0.artists
}
}

fileprivate func venues(annum: Annum) -> [Venue.ID] {
self.compactMap {
guard $0.date.annum == annum else { return nil }
return $0.venue
}
}
}

extension Music {
var artistRankings: [Artist.ID: Ranking] {
let artistShowCounts: [(Artist.ID, Int)] = self.artists.reduce(into: [:]) { d, item in
d[item.id] = self.shows.count(where: { $0.artists.contains(item.id) })
}.map { $0 }

return computeRankings(items: artistShowCounts)
}

var venueRankings: [Venue.ID: Ranking] {
let venuesShowCount: [(Venue.ID, Int)] = self.venues.reduce(into: [:]) { d, item in
d[item.id] = self.shows.count(where: { $0.venue == item.id })
}.map { $0 }

return computeRankings(items: venuesShowCount)
}

var artistSpanRankings: [Artist.ID: Ranking] {
let artistShowSpans: [(Artist.ID, Int)] = self.artists.reduce(into: [:]) { d, item in
d[item.id] = self.shows.dates(withArtist: item.id).yearSpan
}.map { $0 }

return computeRankings(items: artistShowSpans)
}

var venueSpanRankings: [Venue.ID: Ranking] {
let venueShowSpans: [(Venue.ID, Int)] = self.venues.reduce(into: [:]) { d, item in
d[item.id] = self.shows.dates(withVenue: item.id).yearSpan
}.map { $0 }

return computeRankings(items: venueShowSpans)
}

var artistVenueRankings: [Artist.ID: Ranking] {
let artistVenueCounts: [(Artist.ID, Int)] = self.artists.reduce(into: [:]) { d, item in
d[item.id] = Set(self.shows.venues(withArtist: item.id)).count
}.map { $0 }

return computeRankings(items: artistVenueCounts)
}

var venueArtistRankings: [Venue.ID: Ranking] {
let venueArtistCounts: [(Venue.ID, Int)] = self.venues.reduce(into: [:]) { d, item in
d[item.id] = Set(self.shows.artists(withVenue: item.id)).count
}.map { $0 }

return computeRankings(items: venueArtistCounts)
}

private var annums: [Annum] {
Array(shows.map { $0.date.annum }.uniqued())
}

var annumShowRankings: [Annum: Ranking] {
let annumShowCounts: [(Annum, Int)] = annums.map { annum in
(annum, shows.count(where: { $0.date.annum == annum }))
}
return computeRankings(items: annumShowCounts)
}

var annumVenueRankings: [Annum: Ranking] {
let annumVenueCounts: [(Annum, Int)] = annums.map { annum in
(annum, Array(shows.venues(annum: annum).uniqued()).count)
}
return computeRankings(items: annumVenueCounts)
}

var annumArtistRankings: [Annum: Ranking] {
let annumArtistCounts: [(Annum, Int)] = annums.map { annum in
(annum, Array(shows.artists(annum: annum).uniqued()).count)
}
return computeRankings(items: annumArtistCounts)
}

var decadesMap: [Decade: [Annum: Set<Show.ID>]] {
shows.reduce(into: [:]) {
let decade = $1.date.decade
var decadeDict = $0[decade] ?? [:]

let annum = $1.date.annum
var s = decadeDict[annum] ?? Set<Show.ID>()
s.insert($1.id)
decadeDict[annum] = s

$0[decade] = decadeDict
}
}

var artistFirstSets: [Artist.ID: FirstSet] {
var artistsTracked = Set<Artist.ID>()
var firstSetsOrdered = [(Artist.ID, FirstSet)]()

var order = 1
shows.sorted(by: { PartialDate.compareWithUnknownsMuted(lhs: $0.date, rhs: $1.date) }).forEach {
show in
if !show.date.isUnknown {
show.artists.filter { !artistsTracked.contains($0) }.reversed().forEach { artistID in
firstSetsOrdered.append((artistID, FirstSet(rank: .rank(order), date: show.date)))
order += 1

artistsTracked.insert(artistID)
}
}
}

return firstSetsOrdered.reduce(into: [:]) { $0[$1.0] = $1.1 }
}

var venueFirstSets: [Venue.ID: FirstSet] {
var venuesTracked = Set<Venue.ID>()
var firstSetsOrdered = [(Venue.ID, FirstSet)]()

var order = 1
shows.sorted(by: { PartialDate.compareWithUnknownsMuted(lhs: $0.date, rhs: $1.date) }).forEach {
show in
if !show.date.isUnknown && !venuesTracked.contains(show.venue) {
firstSetsOrdered.append((show.venue, FirstSet(rank: .rank(order), date: show.date)))
venuesTracked.insert(show.venue)
order += 1
}
}

return firstSetsOrdered.reduce(into: [:]) { $0[$1.0] = $1.1 }
var tracker: Tracker {
Tracker(shows: self.shows)
}

var relationMap: [String: [String]] {
Expand Down
Loading