FPI 사용자·국가 랭킹 서버 집계 · YouTube 스밍 · Music Shake 참여

This commit is contained in:
Sn-Kinos
2026-10-05 17:49:47 +09:00
parent 5238fc4ef3
commit 96a95a12d1
31 changed files with 738 additions and 116 deletions
@@ -57,11 +57,13 @@ class FirestoreGalaxyRepository implements GalaxyRepository {
// 순위는 1·1·3 공동 순위(C-19). 실값 `fpiScore` 동률만 같은 순위이고 동점 내부는
// fandomId 오름차순으로 고정한다 — 쿼리 순서(동점은 ID 내림차순)를 그대로 쓰지 않는다.
// Stage0 성운은 순위를 매기기 **전에** 뺀다(B-08 · B-17) — 성운이 끼면 정식 행성의
// 순위 번호가 밀린다. 성운은 맨 바깥 궤도 자리(정식 수 + 1)에 둔다.
bool isNebula(QueryDocumentSnapshot<Map<String, dynamic>> d) =>
d.data()['stage'] == 0;
final formal = fandoms.where((d) => !isNebula(d)).toList();
// 랭킹 모집단 밖(B-08 · B-17)은 순위를 매기기 **전에** 뺀다 — 끼면 정식 행성의 순위
// 번호가 밀린다. Stage0 성운과 서버가 `rankingEligible: false`(최근 7 일 유효 활동 없음)로
// 내린 행성이다. 이들은 맨 바깥 궤도 자리(모집단 수 + 1)에 두고 순위는 「-」로 그린다.
// 필드가 아직 없는 문서(집계 배포 전)는 Stage 만으로 판정한다.
bool unranked(QueryDocumentSnapshot<Map<String, dynamic>> d) =>
d.data()['stage'] == 0 || d.data()['rankingEligible'] == false;
final formal = fandoms.where((d) => !unranked(d)).toList();
final planets = <PlanetNode>[
for (final (doc, rank) in rankWithTies(
formal,
@@ -69,8 +71,8 @@ class FirestoreGalaxyRepository implements GalaxyRepository {
(d) => d.id,
))
_node(doc.id, doc.data(), rank, myFandomId),
for (final doc in fandoms.where(isNebula))
_node(doc.id, doc.data(), formal.length + 1, myFandomId),
for (final doc in fandoms.where(unranked))
_node(doc.id, doc.data(), formal.length + 1, myFandomId, ranked: false),
];
final byId = {for (final p in planets) p.id: p};
final membershipIds = [for (final d in (await membershipsF).docs) d.id];
@@ -81,8 +83,15 @@ class FirestoreGalaxyRepository implements GalaxyRepository {
]);
for (final doc in missing) {
final data = doc.data();
if (data != null)
byId[doc.id] = _node(doc.id, data, formal.length + 1, myFandomId);
if (data != null) {
byId[doc.id] = _node(
doc.id,
data,
formal.length + 1,
myFandomId,
ranked: false,
);
}
}
return GalaxySnapshot(
@@ -100,8 +109,10 @@ class FirestoreGalaxyRepository implements GalaxyRepository {
String id,
Map<String, dynamic> data,
int rank,
String myFandomId,
) => PlanetNode(
String myFandomId, {
bool ranked = true,
}) => PlanetNode(
ranked: ranked,
id: id,
stage: switch (data['stage']) {
int n when n >= 0 && n <= 6 => n,