1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
2// See the LICENCE file in the repository root for full licence text.
3
4import BeatmapExtendedJson from 'interfaces/beatmap-extended-json';
5import BeatmapsetJson from 'interfaces/beatmapset-json';
6import { observer } from 'mobx-react';
7import * as React from 'react';
8import { formatDuration, formatNumber } from 'utils/html';
9import { trans } from 'utils/lang';
10
11const bn = 'beatmap-basic-stats';
12
13const statKeys = ['total_length', 'bpm', 'count_circles', 'count_sliders'] as const;
14type StatKey = typeof statKeys[number];
15
16interface Props {
17 beatmap: BeatmapExtendedJson;
18 beatmapset: BeatmapsetJson;
19}
20
21@observer
22export default class BeatmapBasicStats extends React.Component<Props> {
23 render() {
24 return (
25 <div className={bn}>
26 {statKeys.map(this.renderEntry)}
27 </div>
28 );
29 }
30
31 private readonly renderEntry = (key: StatKey) => {
32 const titleParams: Partial<Record<string, string>> = {};
33 let titleAppend = '';
34 const rawValue = this.props.beatmap[key];
35 let value: string;
36
37 switch (key) {
38 case 'bpm': {
39 if (rawValue > 1000) {
40 value = '∞';
41 }
42
43 const offset = this.props.beatmapset.offset;
44 if (offset !== 0) {
45 titleAppend += ` (${trans('beatmapsets.show.stats.offset', { offset: formatNumber(offset) })})`;
46 }
47 break;
48 }
49 case 'total_length':
50 value = formatDuration(this.props.beatmap[key]);
51 titleParams.hit_length = formatDuration(this.props.beatmap.hit_length);
52 break;
53 }
54
55 value ??= formatNumber(rawValue);
56
57 return (
58 <div
59 key={key}
60 className={`${bn}__entry`}
61 title={`${trans(`beatmapsets.show.stats.${key}`, titleParams)}${titleAppend}`}
62 >
63 <div
64 className={`${bn}__entry-icon`}
65 style={{
66 backgroundImage: `url(/images/layout/beatmapset-page/${key}.svg)`,
67 }}
68 />
69 <span>{value}</span>
70 </div>
71 );
72 };
73}