라이브 티커 · 갤럭시 검색 색인 · 주간 랭킹 스냅샷 · 연속 ZAP 상한 · 가입 행성 Zap · 성운 목표 · 랭킹 갱신 안내 · 행성 터치 반응
This commit is contained in:
@@ -5,6 +5,7 @@ import '../../core/data/backend.dart';
|
||||
import '../campaign/campaign_data.dart' show ContributorRank;
|
||||
import '../my/my_data.dart' show PickedPhoto, PhotoRejected;
|
||||
import '../my/my_repository_firestore.dart';
|
||||
import '../home/home_data.dart' show nebulaTargetsFrom;
|
||||
import 'moderation.dart' show reportReasonCodes;
|
||||
import 'planet_data.dart';
|
||||
import '../../core/i18n/app_locale.dart';
|
||||
@@ -165,6 +166,8 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
.limit(1)
|
||||
.get();
|
||||
final memberF = db.doc('fandoms/$fandomId/members/$uid').get();
|
||||
// 성운 전환 목표는 서버 판정과 같은 운영값을 읽는다(앱 상수 아님 · B-10).
|
||||
final policyF = db.doc('config/policy').get();
|
||||
_cursor = null;
|
||||
final postsF = _page(pageSize);
|
||||
|
||||
@@ -173,6 +176,7 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
final memberSnap = await memberF;
|
||||
final member = memberSnap.data() ?? const <String, dynamic>{};
|
||||
final posts = await postsF;
|
||||
final targets = nebulaTargetsFrom((await policyF).data());
|
||||
|
||||
final axes = _map(fandom, 'fpiAxes');
|
||||
final ranks = _map(fandom, 'fpiRanks');
|
||||
@@ -212,6 +216,8 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
isNebula: stage == null ? nebula : stage == 0,
|
||||
members: fandom.intOr('memberCount'),
|
||||
growthPop: fandom.intOr('growthPop'),
|
||||
nebulaTargetPop: targets.pop,
|
||||
nebulaTargetMembers: targets.members,
|
||||
scores: [
|
||||
for (final metric in FpiMetric.values)
|
||||
FpiScore(
|
||||
@@ -236,10 +242,22 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
);
|
||||
}
|
||||
|
||||
/// 행성 랭킹 — 서버 1분 집계(`fnFpiAggregate`)가 적은 `fpiUpdatedAt` 중 가장 늦은 값이 마지막 갱신이다.
|
||||
@override
|
||||
Future<FpiRanking> planetRanking({
|
||||
required FpiMetric metric,
|
||||
int limit = 30,
|
||||
}) async {
|
||||
final ranking = await _planetRanking(metric: metric, limit: limit);
|
||||
final me = (await _backend.db.doc('fandoms/$fandomId').get()).data();
|
||||
return ranking.withUpdate(_time(me?['fpiUpdatedAt']), 1);
|
||||
}
|
||||
|
||||
static DateTime? _time(Object? v) => v is Timestamp ? v.toDate() : null;
|
||||
|
||||
Future<FpiRanking> _planetRanking({
|
||||
required FpiMetric metric,
|
||||
required int limit,
|
||||
}) async {
|
||||
final axis = _axisKey(metric);
|
||||
// 모집단 = 별첨 B 「정식 행성 중 최근 7 일 유효 활동 존재 행성」.
|
||||
@@ -310,11 +328,22 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
);
|
||||
}
|
||||
|
||||
/// 사용자 랭킹 — 서버 5분 집계(`fnRankingCountryAggregate`)가 팬덤 문서에 적는 `memberRankedAt`.
|
||||
@override
|
||||
Future<FpiRanking> userRanking({
|
||||
required FpiMetric metric,
|
||||
required String fandomId,
|
||||
int limit = 30,
|
||||
}) async {
|
||||
final ranking = await _userRanking(metric: metric, fandomId: fandomId, limit: limit);
|
||||
final fandom = (await _backend.db.doc('fandoms/$fandomId').get()).data();
|
||||
return ranking.withUpdate(_time(fandom?['memberRankedAt']), 5);
|
||||
}
|
||||
|
||||
Future<FpiRanking> _userRanking({
|
||||
required FpiMetric metric,
|
||||
required String fandomId,
|
||||
required int limit,
|
||||
}) async {
|
||||
final axis = _axisKey(metric);
|
||||
final uid = _backend.requireUid;
|
||||
@@ -470,6 +499,8 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
return FpiRanking(
|
||||
rows: list,
|
||||
mine: list.where((r) => r.isMine).firstOrNull,
|
||||
updatedAt: _time(doc.data()?['updatedAt']),
|
||||
refreshMinutes: 5,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user