// Author: fruit.com.cn import 'package:flutter/foundation.dart'; import '../../core/data/models/drama.dart'; import '../../core/data/models/home_feed.dart'; /// Ranking boards backed by the feed sections the server already returns. enum RankingBoard { hot, newReleases } /// One ranked title; rank is one-based and mirrors server section order. class RankingEntry { const RankingEntry({required this.rank, required this.drama}); final int rank; final Drama drama; } /// Keeps the active board and turns real feed sections into ranked entries. /// /// The backend does not expose a dedicated ranking endpoint, so this class /// never invents scores: it preserves the order of the `hot` and `new` /// sections and only falls back to the catalog when a section is absent. class RankingLogic extends ChangeNotifier { RankingLogic({required this.sections, required this.fallback}); static const hotSectionCode = 'hot'; static const newSectionCode = 'new'; List sections; List fallback; RankingBoard _board = RankingBoard.hot; RankingBoard get board => _board; List get entries { final sectionCode = _board == RankingBoard.hot ? hotSectionCode : newSectionCode; final source = _sectionDramas(sectionCode); final dramas = source.isEmpty ? fallback : source; final seen = {}; final unique = [ for (final drama in dramas) if (seen.add(drama.id)) drama, ]; return [ for (var index = 0; index < unique.length; index++) RankingEntry(rank: index + 1, drama: unique[index]), ]; } /// Switches boards and notifies only when the visible source changes. void select(RankingBoard next) { if (_board == next) return; _board = next; notifyListeners(); } /// Applies refreshed feed data without rebuilding the page state. void updateSources({ required List sections, required List fallback, }) { this.sections = sections; this.fallback = fallback; notifyListeners(); } List _sectionDramas(String code) { for (final section in sections) { if (section.code == code) return section.dramas; } return const []; } }