@@ -28,21 +28,24 @@ export class Party extends BaseEntity {
28
28
@UpdateDateColumn ( )
29
29
latestTime : Date
30
30
31
- @ManyToOne ( ( ) => Song , { eager : true , nullable : true } )
32
- currentSong : Song | null
31
+ @ManyToOne ( ( ) => Song , { lazy : true , nullable : true } )
32
+ currentSong : Promise < Song | null >
33
33
34
- @OneToMany ( ( ) => VotedSong , votedSong => votedSong . party , { eager : true , cascade : [ 'remove' ] } )
35
- votedSongs : VotedSong [ ]
34
+ @Column ( { nullable : true } )
35
+ currentSongId : number
36
36
37
- @OneToMany ( ( ) => PlayedSong , playedSong => playedSong . party , { eager : true , cascade : [ 'remove' ] } )
38
- playedSongs : PlayedSong [ ]
37
+ @OneToMany ( ( ) => VotedSong , votedSong => votedSong . party , { lazy : true , cascade : [ 'remove' ] } )
38
+ votedSongs : Promise < VotedSong [ ] >
39
+
40
+ @OneToMany ( ( ) => PlayedSong , playedSong => playedSong . party , { lazy : true , cascade : [ 'remove' ] } )
41
+ playedSongs : Promise < PlayedSong [ ] >
39
42
40
43
constructor ( name : string , password ?: string ) {
41
44
super ( )
42
45
43
46
this . name = name
44
47
this . password = password || null
45
- this . currentSong = null
48
+ this . currentSong = Promise . resolve ( null )
46
49
// Don't initialize this.playedSongs or this.votedSongs.
47
50
// this.playedSongs = []
48
51
// this.votedSongs = []
@@ -55,7 +58,7 @@ export class Party extends BaseEntity {
55
58
}
56
59
57
60
public async voteForSong ( song : Song ) {
58
- let votedSong = await VotedSong . findOne ( { song : song , party : this } )
61
+ let votedSong = await VotedSong . findOne ( { where : { songId : song . id , partyId : this . id } } )
59
62
60
63
if ( votedSong ) {
61
64
await votedSong . incrementVote ( )
@@ -68,10 +71,14 @@ export class Party extends BaseEntity {
68
71
}
69
72
70
73
private async removeCurrentSong ( ) {
71
- if ( this . currentSong ) {
72
- const newPlayedSong = new PlayedSong ( this . currentSong , this , await this . getNextSequenceNumber ( ) )
73
- this . currentSong = null
74
- this . playedSongs . push ( newPlayedSong )
74
+ const currentSong = await this . currentSong
75
+
76
+ if ( currentSong ) {
77
+ const newPlayedSong = new PlayedSong ( currentSong , this , await this . getNextSequenceNumber ( ) )
78
+ this . currentSong = Promise . resolve ( null )
79
+ const playedSongs = await this . playedSongs
80
+ playedSongs . push ( newPlayedSong )
81
+ this . playedSongs = Promise . resolve ( playedSongs )
75
82
await Promise . all ( [ newPlayedSong . save ( ) , this . save ( ) ] )
76
83
}
77
84
}
@@ -80,50 +87,40 @@ export class Party extends BaseEntity {
80
87
const highestVotedSong = await this . getHighestVotedSong ( )
81
88
82
89
if ( highestVotedSong ) {
83
- this . currentSong = highestVotedSong . song
90
+ this . currentSongId = ( await highestVotedSong . getSong ( ) ) . id
84
91
await Promise . all ( [ highestVotedSong . remove ( ) , this . save ( ) ] )
85
92
}
86
93
}
87
94
95
+ public async getSortedVotedSongs ( ) {
96
+ const votedSongs = await this . votedSongs
97
+ const songs = await Promise . all ( votedSongs . map ( votedSong => votedSong . getSong ( ) ) )
98
+ const zipped : [ VotedSong , Song ] [ ] = votedSongs . map ( ( votedSong , index ) => {
99
+ return [ votedSong , songs [ index ] ]
100
+ } )
101
+ zipped . sort ( ( [ votedSong1 , song1 ] , [ votedSong2 , song2 ] ) => {
102
+ if ( votedSong1 . count != votedSong2 . count ) {
103
+ return votedSong2 . count - votedSong1 . count
104
+ }
105
+ if ( song1 . title < song2 . title ) {
106
+ return - 1
107
+ }
108
+ return 0
109
+ } )
110
+ return zipped . map ( ( [ votedSong , _song ] ) => votedSong )
111
+ }
112
+
88
113
private async getHighestVotedSong ( ) {
89
114
// TODO: TypeORM can't sort by fields of eagerly joined rows. So we currently retrieve all VotedSong for the party
90
115
// and then sort by song name and then sort by name among the VotedSong with the highest equivalent count and then
91
116
// return the first VotedSong. Optimize this by using the TypeORM query builder to build an SQL query that can
92
117
// JOIN and then order correctly to retrieve a single VotedSong rather than all VotedSong for the party.
93
- return VotedSong . find ( { where : { party : this } , order : { count : 'DESC' } } ) . then ( votedSongs => {
94
- if ( ! Array . isArray ( votedSongs ) || ! votedSongs . length ) {
95
- return null
96
- } else {
97
- const highestCount = votedSongs [ 0 ] . count
98
- return votedSongs
99
- . filter ( votedSong => votedSong . count == highestCount )
100
- . sort ( ( votedSong1 , votedSong2 ) => {
101
- if ( votedSong1 . count != votedSong2 . count ) {
102
- return votedSong2 . count - votedSong1 . count
103
- }
104
- if ( votedSong1 . song . title < votedSong2 . song . title ) {
105
- return - 1
106
- }
107
- return 0
108
- } ) [ 0 ]
109
- }
110
- } )
118
+ const sortedVotedSongs = await this . getSortedVotedSongs ( )
119
+ return sortedVotedSongs [ 0 ]
111
120
}
112
121
113
122
private async getNextSequenceNumber ( ) {
114
123
const latestSong = await PlayedSong . findOne ( { where : { party : this } , order : { sequenceNumber : 'DESC' } } )
115
124
return latestSong ? latestSong . sequenceNumber + 1 : 0
116
125
}
117
-
118
- public sortVotedSongs ( ) {
119
- this . votedSongs . sort ( ( votedSong1 , votedSong2 ) => {
120
- if ( votedSong1 . count != votedSong2 . count ) {
121
- return votedSong2 . count - votedSong1 . count
122
- }
123
- if ( votedSong1 . song . title < votedSong2 . song . title ) {
124
- return - 1
125
- }
126
- return 0
127
- } )
128
- }
129
126
}
0 commit comments