FPI 사용자·국가 랭킹 서버 집계 · YouTube 스밍 · Music Shake 참여
This commit is contained in:
@@ -134,9 +134,9 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
final axes = _map(fandom, 'fpiAxes');
|
||||
final ranks = _map(fandom, 'fpiRanks');
|
||||
final myTop = _map(member, 'topPercentByAxis');
|
||||
// MOCK: `topPercentByAxis` 는 서버 산출값인데 이를 쓰는 집계 함수가 아직
|
||||
// 없습니다. 필드는 실연동으로 읽고, **값이 없으면 null** 로 둡니다 —
|
||||
// 100%(최하위)로 채우면 없는 값이 사실처럼 보입니다. 대조표 3-5 참조.
|
||||
// `topPercentByAxis` 는 서버 5 분 집계(`fnRankingCountryAggregate`)가 적는다.
|
||||
// **값이 없으면 null** — 그 축 기여가 0 이거나 모집단(B-17) 밖이다. 100%(최하위)로
|
||||
// 채우면 없는 값이 사실처럼 보인다.
|
||||
int? myTopOf(FpiMetric metric) => myTop[_axisKey(metric)] is num
|
||||
? myTop.intOr(_axisKey(metric))
|
||||
: null;
|
||||
@@ -189,9 +189,7 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
posts: posts,
|
||||
// 한 축이라도 서버 값이 없으면 배지로 알린다. 화면이 이 문구를 그대로
|
||||
// 띄운다 — 「집계 준비 중」 카드만으로는 이유가 보이지 않는다(대조표 3-5).
|
||||
mockNote: FpiMetric.values.any((m) => myTopOf(m) == null)
|
||||
? '「내 기여 상위 %」 집계 함수가 아직 없습니다'
|
||||
: null,
|
||||
mockNote: null,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -288,18 +286,7 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
(d) => _raw(d.data(), axis),
|
||||
(d) => d.id,
|
||||
))
|
||||
FpiRankRow(
|
||||
id: doc.id,
|
||||
rank: rank,
|
||||
// UID·이메일을 이름 자리에 내보내지 않는다(G-07).
|
||||
name: publicName(doc.data()['nickname']),
|
||||
value: _map(doc.data(), 'fpiAxes').intOr(axis),
|
||||
// MOCK: 멤버의 직전 축별 순위(`rankPrevByAxis`)를 쓰는 서버 집계가
|
||||
// 아직 없습니다. 필드가 없으면 현재 순위를 그대로 넣어 동향이 0 이 되고,
|
||||
// 화면은 ▲▼ 를 그리지 않습니다. 대조표 3-5 참조.
|
||||
change: _map(doc.data(), 'rankPrevByAxis').intOr(axis, rank) - rank,
|
||||
isMine: doc.id == uid,
|
||||
),
|
||||
_userRow(doc.data(), id: doc.id, axis: axis, fallbackRank: rank, uid: uid),
|
||||
];
|
||||
|
||||
// 한 줄도 직전 순위를 갖고 있지 않으면 동향은 전부 0 이다. 그 사실을 배지로
|
||||
@@ -317,22 +304,45 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
// Figma `546:14668` 「나의 랭킹 영역」은 내가 몇 등이든 떠야 한다.
|
||||
final me = (await members.doc(uid).get()).data();
|
||||
if (me == null) return FpiRanking(rows: rows, mockNote: note);
|
||||
final myValue = _map(me, 'fpiAxes').intOr(axis);
|
||||
// 실값보다 큰 멤버 수 + 1 = 공동 순위(C-19). 반올림한 값으로 세면 동률이 생긴다.
|
||||
final above = await members
|
||||
.where('fpiAxes.$axis', isGreaterThan: _raw(me, axis))
|
||||
.count()
|
||||
.get();
|
||||
// 서버 순위가 없을 때만 실값보다 큰 멤버 수 + 1 = 공동 순위(C-19)로 센다.
|
||||
final serverRank = _map(me, 'rankByAxis')[axis];
|
||||
final fallback = serverRank is num
|
||||
? 0
|
||||
: ((await members
|
||||
.where('fpiAxes.$axis', isGreaterThan: _raw(me, axis))
|
||||
.count()
|
||||
.get())
|
||||
.count ??
|
||||
rows.length) +
|
||||
1;
|
||||
return FpiRanking(
|
||||
rows: rows,
|
||||
mockNote: note,
|
||||
mine: FpiRankRow(
|
||||
id: uid,
|
||||
rank: (above.count ?? rows.length) + 1,
|
||||
name: publicName(me['nickname'], appL10n.commonMe),
|
||||
value: myValue,
|
||||
isMine: true,
|
||||
),
|
||||
mine: _userRow(me, id: uid, axis: axis, fallbackRank: fallback, uid: uid,
|
||||
name: appL10n.commonMe),
|
||||
);
|
||||
}
|
||||
|
||||
/// 사용자 랭킹 한 줄. 순위 · 직전 순위는 서버 5 분 집계(`rankByAxis` · `rankPrevByAxis`)를
|
||||
/// 읽는다 — 상위 % 와 같은 원천이라 두 값이 갈리지 않는다. 서버 값이 없을 때만 [fallbackRank].
|
||||
static FpiRankRow _userRow(
|
||||
Map<String, dynamic> data, {
|
||||
required String id,
|
||||
required String axis,
|
||||
required int fallbackRank,
|
||||
required String uid,
|
||||
String? name,
|
||||
}) {
|
||||
final rank = _map(data, 'rankByAxis').intOr(axis, fallbackRank);
|
||||
return FpiRankRow(
|
||||
id: id,
|
||||
rank: rank,
|
||||
// UID·이메일을 이름 자리에 내보내지 않는다(G-07).
|
||||
name: publicName(data['nickname'], name),
|
||||
value: _map(data, 'fpiAxes').intOr(axis),
|
||||
// 순위 동향 = 직전 순위 − 현재 순위. 직전 값이 없으면 0(▲▼ 없음).
|
||||
change: _map(data, 'rankPrevByAxis').intOr(axis, rank) - rank,
|
||||
isMine: id == uid,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user