Skip to content

Commit 294105f

Browse files
committed
feat(ongeki): new technical rating display
1 parent 552d7ea commit 294105f

14 files changed

+622
-137
lines changed

src/app/sega/ongeki/model/OngekiEnums.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ export enum BattleRank {
5353
}
5454

5555
export enum TechnicalRank {
56-
Invalid = -1,
57-
Begin = 0,
5856
None = 0,
5957
D = 1,
6058
C = 2,
@@ -68,7 +66,6 @@ export enum TechnicalRank {
6866
SS = 10,
6967
SSS = 11,
7068
SSS1 = 12,
71-
End = 13,
7269
}
7370

7471
// The AttributeType send by client is + 1. So the value here is start from 1

src/app/sega/ongeki/model/OngekiProfile.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export interface DisplayOngekiProfile {
1818
medalCount: number;
1919
playerRating: number;
2020
highestRating: number;
21+
newPlayerRating: number;
22+
newHighestRating: number;
2123
battlePoint: number;
2224
bestBattlePoint: number;
2325
rankId: number;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {OngekiMusic} from './OngekiMusic';
2+
3+
export interface PlayerNewRatingItem {
4+
musicId: number;
5+
level: number;
6+
techScoreMax: number;
7+
platinumScoreMax: number;
8+
platinumScoreStar: number;
9+
isFullBell?: boolean;
10+
isFullCombo?: boolean;
11+
isAllBreak?: boolean;
12+
clearMarkType?: ClearMarkType;
13+
musicInfo?: OngekiMusic;
14+
}
15+
16+
export enum ClearMarkType {
17+
None,
18+
FullCombo,
19+
AllBreak,
20+
AllBreakPlus
21+
}

src/app/sega/ongeki/model/PlayerRatingItem.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export interface PlayerRatingItem {
55
musicId: number;
66
level: number;
77
value: number;
8+
platinumScoreMax: number;
9+
platinumScoreStar: number;
810
musicInfo?: OngekiMusic;
911
bossCardInfo?: OngekiCard;
1012
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { TestBed } from '@angular/core/testing';
2+
3+
import { NewRatingService } from './new-rating.service';
4+
5+
describe('RatingService', () => {
6+
let service: NewRatingService;
7+
8+
beforeEach(() => {
9+
TestBed.configureTestingModule({});
10+
service = TestBed.inject(NewRatingService);
11+
});
12+
13+
it('should be created', () => {
14+
expect(service).toBeTruthy();
15+
});
16+
});
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import { Injectable } from '@angular/core';
2+
import {ClearMarkType, PlayerNewRatingItem} from './model/PlayerNewRatingItem';
3+
import {OngekiMusic} from './model/OngekiMusic';
4+
5+
@Injectable({
6+
providedIn: 'root'
7+
})
8+
export class NewRatingService {
9+
10+
constructor() { }
11+
12+
public getTechnicalRankIDByScore(score: number): TechnicalRankID {
13+
const entries = Array.from(technicalRankTable.entries());
14+
entries.sort((a, b) => b[1] - a[1]);
15+
const found = entries.find(([_, value]) => score >= value);
16+
return found ? found[0] : TechnicalRankID.None;
17+
}
18+
19+
public calcRate1000(ratingItem: PlayerNewRatingItem, type: NewRatingType): number {
20+
if (!ratingItem.musicInfo) { return 0; }
21+
else if (type === NewRatingType.Best) {
22+
return this.calcTechnicalScoreRate1000(ratingItem);
23+
}
24+
else if (type === NewRatingType.New) {
25+
const rate1000 = this.calcTechnicalScoreRate1000(ratingItem);
26+
return Math.floor(rate1000 / 5) * 5;
27+
}
28+
else if (type === NewRatingType.Platinum) {
29+
return this.calcPlatinumScoreRate1000(ratingItem);
30+
}
31+
}
32+
33+
calcTechnicalScoreRate1000(ratingItem: PlayerNewRatingItem) {
34+
const score = ratingItem.techScoreMax;
35+
const clearMarkType = ratingItem.clearMarkType;
36+
const isFullBell = ratingItem.isFullBell;
37+
38+
const level1000 = this.getLevel1000(ratingItem.musicInfo, ratingItem.level);
39+
let rate1000 = 0;
40+
41+
if (score <= rateTbl[0].score) {
42+
rate1000 = Math.floor((level1000 + rateTbl[0].bonus1000) * (score - 500000) / (rateTbl[0].score - 500000));
43+
} else {
44+
for (let i = 1; i < rateTbl.length; i++) {
45+
const nextRate = rateTbl[i];
46+
if (score <= nextRate.score) {
47+
const rate = rateTbl[i - 1];
48+
const techScoreRank = this.getTechnicalRankIDByScore(score);
49+
const clearMarkBonus = clearMarkRateTbl.get(clearMarkType) || 0;
50+
const fullBellBonus = fullBellRateTbl.get(isFullBell) || 0;
51+
let teckRankBonus = 0;
52+
53+
for (const rank of teckRankOrder) {
54+
if (techScoreRank < rank) {
55+
break;
56+
}
57+
teckRankBonus = teckRankRateTbl.get(rank) || 0;
58+
}
59+
60+
let num4 = level1000 + rate.bonus1000;
61+
const bonusDiff = nextRate.bonus1000 - rate.bonus1000;
62+
const scoreDiff = score - rate.score;
63+
const rateDiff = nextRate.score - rate.score;
64+
num4 += Math.floor((bonusDiff * scoreDiff) / rateDiff);
65+
rate1000 = num4 + clearMarkBonus + teckRankBonus + fullBellBonus;
66+
break;
67+
}
68+
}
69+
}
70+
71+
return Math.max(rate1000, 0);
72+
}
73+
74+
calcPlatinumScoreRate1000(ratingItem: PlayerNewRatingItem): number {
75+
const level = this.getLevel(ratingItem.musicInfo, ratingItem.level);
76+
const platinumScoreStar = Math.min(ratingItem.platinumScoreStar, 5);
77+
const rate1000 = platinumScoreStar * Math.pow(level, 2);
78+
79+
return Math.max(Math.floor(rate1000), 0);
80+
}
81+
82+
getLevel1000(musicInfo: OngekiMusic, level: number) {
83+
const level100 = this.getLevel100(musicInfo, level);
84+
return level100 * 10;
85+
}
86+
87+
getLevel100(musicInfo: OngekiMusic, level: number) {
88+
if (!musicInfo) {
89+
return null;
90+
}
91+
let levelData: string;
92+
if (level === 0) {
93+
levelData = musicInfo.level0;
94+
} else if (level === 1) {
95+
levelData = musicInfo.level1;
96+
} else if (level === 2) {
97+
levelData = musicInfo.level2;
98+
} else if (level === 3) {
99+
levelData = musicInfo.level3;
100+
} else if (level === 10) {
101+
levelData = musicInfo.level4;
102+
}
103+
const levelDatas = levelData.split(',');
104+
if (levelDatas.length !== 2) {
105+
return null;
106+
}
107+
108+
return Math.floor(parseInt(levelDatas[0], 10) * 100 + parseInt(levelDatas[1], 10) + 0.5);
109+
}
110+
111+
public getLevel(musicInfo: OngekiMusic, level: number) {
112+
const level100 = this.getLevel100(musicInfo, level);
113+
return level100 / 100;
114+
}
115+
116+
}
117+
118+
export enum NewRatingType {
119+
New, Best, Platinum
120+
}
121+
122+
enum TechnicalRankID {
123+
None,
124+
D,
125+
C,
126+
B,
127+
BB,
128+
BBB,
129+
A,
130+
AA,
131+
AAA,
132+
S,
133+
SS,
134+
SSS,
135+
SSS1
136+
}
137+
138+
class RateTbl {
139+
constructor(public score: number, public bonus1000: number) {
140+
}
141+
}
142+
143+
const rateTbl: RateTbl[] = [
144+
new RateTbl(800000, -6000),
145+
new RateTbl(900000, -4000),
146+
new RateTbl(970000, 0),
147+
new RateTbl(990000, 750),
148+
new RateTbl(1000000, 1250),
149+
new RateTbl(1007500, 1750),
150+
new RateTbl(1010000, 2000)
151+
];
152+
153+
const clearMarkRateTbl = new Map<ClearMarkType, number>([
154+
[ClearMarkType.None, 0],
155+
[ClearMarkType.FullCombo, 100],
156+
[ClearMarkType.AllBreak, 300],
157+
[ClearMarkType.AllBreakPlus, 350]
158+
]);
159+
160+
const fullBellRateTbl = new Map<boolean, number>([
161+
[false, 0],
162+
[true, 50]
163+
]);
164+
165+
const teckRankRateTbl = new Map<TechnicalRankID, number>([
166+
[TechnicalRankID.S, 0],
167+
[TechnicalRankID.SS, 100],
168+
[TechnicalRankID.SSS, 200],
169+
[TechnicalRankID.SSS1, 300]
170+
]);
171+
172+
const technicalRankTable = new Map<TechnicalRankID, number>([
173+
[TechnicalRankID.D, 0],
174+
[TechnicalRankID.C, 500000],
175+
[TechnicalRankID.B, 700000],
176+
[TechnicalRankID.BB, 750000],
177+
[TechnicalRankID.BBB, 800000],
178+
[TechnicalRankID.A, 850000],
179+
[TechnicalRankID.AA, 900000],
180+
[TechnicalRankID.AAA, 940000],
181+
[TechnicalRankID.S, 970000],
182+
[TechnicalRankID.SS, 990000],
183+
[TechnicalRankID.SSS, 1000000],
184+
[TechnicalRankID.SSS1, 1007500]
185+
]);
186+
187+
const teckRankOrder: TechnicalRankID[] = [
188+
TechnicalRankID.S,
189+
TechnicalRankID.SS,
190+
TechnicalRankID.SSS,
191+
TechnicalRankID.SSS1
192+
];

src/app/sega/ongeki/ongeki-battle-point/ongeki-battle-point.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ export class OngekiBattlePointComponent implements OnInit {
6464
musicId: Number(value[0]),
6565
level: Number(value[1]),
6666
value: Number(value[2]),
67+
platinumScoreMax: Number(value[3]),
68+
platinumScoreStar: Number(value[4]),
6769
};
6870
this.dbService.getByID<OngekiMusic>('ongekiMusic', item.musicId).subscribe(
6971
x => {

src/app/sega/ongeki/ongeki-card/ongeki-card.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ <h1 class="page-heading">{{ 'Ongeki.Card.Title' | translate }}</h1>
4040
<ng-container *ngIf="currentDeck">
4141
<div class="deck-row row row-cols-3">
4242
<ng-container *ngFor="let item of currentDeck;let i = index">
43-
<div class="col p-2">
43+
<div class="col">
4444
<div class="cards-col">
4545
<app-ongeki-card-item
4646
(click)="open(selectCard)"

src/app/sega/ongeki/ongeki-rating/ongeki-rating.component.css

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
.rating-card{
2+
min-width: 180px;
23
}
34
.jacket{
45
width: 5.6rem;
56
aspect-ratio: 1;
67
}
78

9+
.new-jacket{
10+
width: 3.6rem;
11+
aspect-ratio: 1;
12+
border-top-left-radius: var(--bs-border-radius) !important;
13+
}
14+
@media (min-width:1400px){
15+
.col-xxl-{
16+
flex:0 0 auto;width:20%
17+
}
18+
}
819
.difficulty {
9-
font-size: 12px;
20+
font-size: 0.7em;
1021
}
1122

1223
.difficulty-basic {
@@ -38,3 +49,16 @@
3849
border: 1px solid var(--bs-danger);
3950
color: var(--bs-danger);
4051
}
52+
53+
.honor-badge {
54+
aspect-ratio: 1;
55+
width: 28px;
56+
}
57+
58+
.honor{
59+
height: 28px;
60+
}
61+
62+
@media (max-width:400px){
63+
.row-cols-xxs-1>*{flex:0 0 auto;width:100%}
64+
}

0 commit comments

Comments
 (0)