the browser-facing portion of osu!
at master 2.1 kB view raw
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}