@@ -7,7 +7,8 @@ import { FFunction } from './commands';
7
7
import { computeStatistics } from './funcs' ;
8
8
import { FishEvents } from './globals' ;
9
9
import { dataClass , serialize } from './io' ;
10
- import { formatTime } from './utils' ;
10
+ import { formatTime , match } from './utils' ;
11
+ import { Gamemode } from './config' ;
11
12
12
13
type FinishedMapRunData = {
13
14
winTeam :Team ;
@@ -79,7 +80,7 @@ export class PartialMapRun {
79
80
} ) :FinishedMapRun {
80
81
return new FinishedMapRun ( {
81
82
winTeam,
82
- success : winTeam == Vars . state . rules . defaultTeam ,
83
+ success : Gamemode . pvp ( ) ? true : winTeam == Vars . state . rules . defaultTeam ,
83
84
startTime : this . startTime ,
84
85
endTime : Date . now ( ) ,
85
86
maxPlayerCount : this . maxPlayerCount
@@ -161,8 +162,13 @@ export class FMap extends dataClass<FMapData>() {
161
162
const lateRTVs = this . runs . filter ( r => r . outcome ( ) [ 1 ] === "late rtv" ) . length ;
162
163
const significantRunCount = allRunCount - earlyRTVs ;
163
164
const totalLosses = losses + lateRTVs ;
164
- const durations = this . runs . map ( r => r . duration ( ) / 1000 ) ; //convert to seconds
165
+ const durations = this . runs . filter ( r => r . outcome ( ) [ 0 ] !== "rtv" ) . map ( r => r . duration ( ) / 1000 ) ; //convert to seconds
165
166
const durationStats = computeStatistics ( durations ) ;
167
+ const teamWins = this . runs . filter ( r => r . success ) . reduce ( ( acc , item ) => {
168
+ acc [ item . winTeam . name ] = ( acc [ item . winTeam . name ] ?? 0 ) + 1 ;
169
+ return acc ;
170
+ } , { } as Record < string , number > ) ;
171
+ const teamWinRate = Object . fromEntries ( Object . entries ( teamWins ) . map ( ( [ team , wins ] ) => [ team , wins / victories ] ) ) ;
166
172
return {
167
173
allRunCount,
168
174
significantRunCount,
@@ -177,14 +183,44 @@ export class FMap extends dataClass<FMapData>() {
177
183
averagePlaytime : durationStats . average ,
178
184
shortestWinTime : Math . min ( ...this . runs . filter ( r => r . outcome ( ) [ 0 ] === "win" ) . map ( r => r . duration ( ) ) ) ,
179
185
longestTime : durationStats . highest ,
186
+ shortestTime : durationStats . lowest ,
180
187
averageHighestPlayerCount : computeStatistics ( this . runs . map ( r => r . maxPlayerCount ) ) . average ,
188
+ teamWins,
189
+ teamWinRate,
181
190
} ;
182
191
}
183
192
displayStats ( f :FFunction ) :string | null {
184
193
const map = this . map ; if ( ! map ) return null ;
185
194
const stats = this . stats ( ) ;
186
195
const rules = this . rules ( ) ! ;
187
196
197
+ const modeSpecificStats = match ( Gamemode . name ( ) , {
198
+ attack : `\
199
+ [accent]Total runs: ${ stats . allRunCount } (${ stats . victories } wins, ${ stats . totalLosses } losses, ${ stats . earlyRTVs } RTVs)
200
+ [accent]Outcomes: ${ f . percent ( stats . winRate , 1 ) } wins, ${ f . percent ( stats . lossRate , 1 ) } losses, ${ f . percent ( stats . earlyRTVRate , 1 ) } RTVs
201
+ [accent]Average playtime: ${ formatTime ( stats . averagePlaytime ) }
202
+ [accent]Shortest win time: ${ formatTime ( stats . shortestWinTime ) } ` ,
203
+ survival : `\
204
+ [accent]Total runs: ${ stats . allRunCount } (${ stats . earlyRTVs } RTVs)
205
+ [accent]RTV rate: ${ f . percent ( stats . earlyRTVRate , 1 ) }
206
+ [accent]Average duration: ${ formatTime ( stats . averagePlaytime ) }
207
+ [accent]Longest duration: ${ formatTime ( stats . longestTime ) } ` ,
208
+ pvp : `\
209
+ [accent]Total runs: ${ stats . allRunCount } (${ stats . earlyRTVs } RTVs)
210
+ [accent]Team win rates: ${ Object . entries ( stats . teamWinRate ) . map ( ( [ team , rate ] ) => `${ team } ${ f . percent ( rate , 1 ) } ` ) . join ( ", " ) }
211
+ [accent]RTV rate: ${ f . percent ( stats . earlyRTVRate , 1 ) }
212
+ [accent]Average match duration: ${ formatTime ( stats . averagePlaytime ) }
213
+ [accent]Shortest match duration: ${ formatTime ( stats . shortestWinTime ) } ` ,
214
+ hexed : `\
215
+ [accent]Total runs: ${ stats . allRunCount } (${ stats . earlyRTVs } RTVs)
216
+ [accent]RTV rate: ${ f . percent ( stats . earlyRTVRate , 1 ) }
217
+ [accent]Average match duration: ${ formatTime ( stats . averagePlaytime ) }
218
+ [accent]Shortest match duration: ${ formatTime ( stats . shortestWinTime ) } ` ,
219
+ sandbox : `\
220
+ [accent]Total plays: ${ stats . allRunCount }
221
+ [accent]Average play time: ${ formatTime ( stats . averagePlaytime ) }
222
+ [accent]Shortest play time: ${ formatTime ( stats . shortestTime ) } ` ,
223
+ } , "" ) ;
188
224
return ( `\
189
225
[coral]Information for map ${ map . name ( ) } [gray](${ map . file . name ( ) } )[coral]:
190
226
[accent]Map by: ${ map . author ( ) }
@@ -193,11 +229,8 @@ export class FMap extends dataClass<FMapData>() {
193
229
[accent]Last updated: ${ new Date ( map . file . lastModified ( ) ) . toLocaleDateString ( ) }
194
230
[accent]BvB allowed: ${ f . boolGood ( rules . placeRangeCheck ) } , unit item transfer allowed: ${ f . boolGood ( rules . onlyDepositCore ) }
195
231
196
- [accent]Total runs: ${ stats . allRunCount } (${ stats . victories } wins, ${ stats . totalLosses } losses, ${ stats . earlyRTVs } RTVs)
197
- [accent]Outcomes: ${ f . percent ( stats . winRate , 1 ) } wins, ${ f . percent ( stats . lossRate , 1 ) } losses, ${ f . percent ( stats . earlyRTVRate , 1 ) } RTVs
198
- [accent]Average playtime: ${ formatTime ( stats . averagePlaytime ) }
199
- [accent]Shortest win time: ${ formatTime ( stats . shortestWinTime ) }
200
- [accent]Longest run: ${ formatTime ( stats . longestTime ) }
232
+ ${ modeSpecificStats }
233
+ [accent]Longest play time: ${ formatTime ( stats . longestTime ) }
201
234
[accent]Average player count: ${ stats . averageHighestPlayerCount } `
202
235
) ;
203
236
}
0 commit comments