1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Snapshot from http://www.nasdaq.com/screening/company-list.aspx
6// Fetched 2/23/2014.
7// "Symbol","Name","LastSale","MarketCap","IPOyear","Sector","industry","Summary Quote",
8// Data in stock_data.json
9
10import 'dart:convert';
11import 'dart:math' as math;
12
13import 'package:flutter/foundation.dart';
14import 'package:http/http.dart' as http;
15
16final math.Random _rng = math.Random();
17
18class Stock {
19 Stock(this.symbol, this.name, this.lastSale, this.marketCap, this.percentChange);
20
21 Stock.fromFields(List<String> fields) {
22 // TODO(jackson): This class should only have static data, not lastSale, etc.
23 // "Symbol","Name","LastSale","MarketCap","IPOyear","Sector","industry","Summary Quote",
24 lastSale = 0.0;
25 try {
26 lastSale = double.parse(fields[2]);
27 } catch (_) {}
28 symbol = fields[0];
29 name = fields[1];
30 marketCap = fields[4];
31 percentChange = (_rng.nextDouble() * 20) - 10;
32 }
33
34 late String symbol;
35 late String name;
36 late double lastSale;
37 late String marketCap;
38 late double percentChange;
39}
40
41class StockData extends ChangeNotifier {
42 StockData() {
43 if (actuallyFetchData) {
44 _httpClient = http.Client();
45 _fetchNextChunk();
46 }
47 }
48
49 final List<String> _symbols = <String>[];
50 final Map<String, Stock> _stocks = <String, Stock>{};
51
52 List<String> get allSymbols => _symbols;
53
54 Stock? operator [](String symbol) => _stocks[symbol];
55
56 bool get loading => _httpClient != null;
57
58 void add(List<dynamic> data) {
59 for (final List<dynamic> fields in data.cast<List<dynamic>>()) {
60 final Stock stock = Stock.fromFields(fields.cast<String>());
61 _symbols.add(stock.symbol);
62 _stocks[stock.symbol] = stock;
63 }
64 _symbols.sort();
65 notifyListeners();
66 }
67
68 static const int _chunkCount = 30;
69 int _nextChunk = 0;
70
71 Uri _urlToFetch(int chunk) =>
72 Uri.https('domokit.github.io', 'examples/stocks/data/stock_data_$chunk.json');
73
74 http.Client? _httpClient;
75
76 static bool actuallyFetchData = true;
77
78 void _fetchNextChunk() {
79 _httpClient!.get(_urlToFetch(_nextChunk++)).then<void>((http.Response response) {
80 final String json = response.body;
81 const JsonDecoder decoder = JsonDecoder();
82 add(decoder.convert(json) as List<dynamic>);
83 if (_nextChunk < _chunkCount) {
84 _fetchNextChunk();
85 } else {
86 _end();
87 }
88 });
89 }
90
91 void _end() {
92 _httpClient!.close();
93 _httpClient = null;
94 }
95}
96