1// Copyright 2014 The Chromium 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 // FIXME: 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 String symbol; 35 String name; 36 double lastSale; 37 String marketCap; 38 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 Iterable<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 (List<dynamic> fields in data) { 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 String _urlToFetch(int chunk) { 72 return 'https://domokit.github.io/examples/stocks/data/stock_data_$chunk.json'; 73 } 74 75 http.Client _httpClient; 76 77 static bool actuallyFetchData = true; 78 79 void _fetchNextChunk() { 80 _httpClient.get(_urlToFetch(_nextChunk++)).then<void>((http.Response response) { 81 final String json = response.body; 82 if (json == null) { 83 debugPrint('Failed to load stock data chunk ${_nextChunk - 1}'); 84 _end(); 85 return; 86 } 87 const JsonDecoder decoder = JsonDecoder(); 88 add(decoder.convert(json)); 89 if (_nextChunk < _chunkCount) { 90 _fetchNextChunk(); 91 } else { 92 _end(); 93 } 94 }); 95 } 96 97 void _end() { 98 _httpClient?.close(); 99 _httpClient = null; 100 } 101} 102