import "package:capstone_project/models/event_signal.dart"; import "package:capstone_project/utils/agrigator.dart"; class WatchedStock { final String ticker; final String companyName; EventSignal? latestSignal; List signalHistory; WatchedStock({ required this.ticker, required this.companyName, this.latestSignal, List? signalHistory, }) : signalHistory = signalHistory ?? []; factory WatchedStock.fromJson(Map json) { final signalHistoryJson = (json["signalHistory"] as List? ?? []) .whereType>() .map(_eventSignalFromStoredJson) .whereType() .toList(); final latestSignalJson = json["latestSignal"]; final latest = latestSignalJson is Map ? _eventSignalFromStoredJson(latestSignalJson) : null; return WatchedStock( ticker: (json["ticker"] ?? "").toString(), companyName: (json["companyName"] ?? "").toString(), latestSignal: latest ?? (signalHistoryJson.isNotEmpty ? signalHistoryJson.first : null), signalHistory: signalHistoryJson, ); } Map toJson() { return { "ticker": ticker, "companyName": companyName, "latestSignal": latestSignal?.toJson(), "signalHistory": signalHistory.map((signal) => signal.toJson()).toList(), }; } // returns null (and logs) when the stored payload is from the pre-rework // schema — we'd rather drop it than invent impact/direction values. static EventSignal? _eventSignalFromStoredJson(Map json) { final articles = (json["articles"] as List? ?? []) .whereType>() .map(FeedItem.fromJson) .toList(); try { return EventSignal.fromJson(json, articles); } on LegacySignalException catch (e) { print("[watched_stock] dropping legacy signal: ${e.message}"); return null; } } }