From 1cc0b846c879205106b92ff279b60601fcc44ce9 Mon Sep 17 00:00:00 2001 From: quiz3 <113859565+quiz3@users.noreply.github.com> Date: Sun, 26 Nov 2023 18:15:46 -0500 Subject: [PATCH 1/5] GetNews table added, but bug discovered in use case --- .../GetNews/GetNewsPresenter.java | 9 +- .../GetNews/GetNewsState.java | 46 +++++- .../use_cases/GetNews/GetNewsOutputData.java | 27 ++- src/main/java/view/BuyView.java | 3 +- src/main/java/view/GetNewsView.java | 154 +++++++++++++----- 5 files changed, 178 insertions(+), 61 deletions(-) diff --git a/src/main/java/interface_adapters/GetNews/GetNewsPresenter.java b/src/main/java/interface_adapters/GetNews/GetNewsPresenter.java index e690fdd..64bab2c 100644 --- a/src/main/java/interface_adapters/GetNews/GetNewsPresenter.java +++ b/src/main/java/interface_adapters/GetNews/GetNewsPresenter.java @@ -16,13 +16,20 @@ public GetNewsPresenter(ViewManagerModel viewManagerModel, GetNewsViewModel getN @Override public void prepareSuccessView(GetNewsOutputData response) { // TODO: On success, show articles in a list (aka. table) + GetNewsState state = getNewsViewModel.getState(); + + state.setRenderNewInfo(true); + state.setNewsItems(response.getNewsItems()); + state.setTicker(response.getTicker()); + + getNewsViewModel.firePropertyChanged(); } @Override public void prepareFailView(String error) { - // TODO GetNewsState state = getNewsViewModel.getState(); state.setTickerError(error); getNewsViewModel.firePropertyChanged(); } + } diff --git a/src/main/java/interface_adapters/GetNews/GetNewsState.java b/src/main/java/interface_adapters/GetNews/GetNewsState.java index ebaf450..b16dcef 100644 --- a/src/main/java/interface_adapters/GetNews/GetNewsState.java +++ b/src/main/java/interface_adapters/GetNews/GetNewsState.java @@ -1,24 +1,54 @@ package interface_adapters.GetNews; +import java.util.List; +import java.util.Map; + public class GetNewsState { private String tickerError = null; - private String ticker = null; + private String ticker = ""; + List> newsItems; + private Boolean renderNewInfo; - public GetNewsState(String ticker, String tickerError) { - this.ticker = ticker; + public String getTickerError() { + return tickerError; + } + + public void setTickerError(String tickerError) { this.tickerError = tickerError; } - public String getTickerError() {return tickerError;} + public String getTicker() { + return ticker; + } - public void setTickerError(String tickerError) {this.tickerError = tickerError;} + public void setTicker(String ticker) { + this.ticker = ticker; + } - public String getTicker() {return ticker;} + public List> getNewsItems() { + return this.newsItems; + } - public void setTicker(String ticker) {this.ticker = ticker;} + public void setNewsItems(List> newsItems) { + this.newsItems = newsItems; + } + + public Map getNewsItem() { + return this.newsItems.get(0); + } + + public Boolean getRenderNewInfo() { + return renderNewInfo; + } + + public void setRenderNewInfo(Boolean renderNewInfo) { + this.renderNewInfo = renderNewInfo; + } // Due to the ViewModel's default constructor call, we must explicitly define the default constructor. // So, we overload the copy constructor. - public GetNewsState() {} + public GetNewsState() { + + } } diff --git a/src/main/java/use_cases/GetNews/GetNewsOutputData.java b/src/main/java/use_cases/GetNews/GetNewsOutputData.java index ef22690..a08cf63 100644 --- a/src/main/java/use_cases/GetNews/GetNewsOutputData.java +++ b/src/main/java/use_cases/GetNews/GetNewsOutputData.java @@ -9,29 +9,28 @@ public class GetNewsOutputData { String ticker; - List> news_items; + List> newsItems; - public GetNewsOutputData(String ticker, List company_news_items) { + public GetNewsOutputData(String ticker, List companyNewsItems) { this.ticker = ticker; - this.news_items = new ArrayList>(); + this.newsItems = new ArrayList>(); - for (CompanyNews company_news : company_news_items) { - Map news_item = new HashMap<>(); + for (CompanyNews companyNews : companyNewsItems) { + Map newsItem = new HashMap<>(); - news_item.put("category", company_news.getCategory()); - news_item.put("datetime", company_news.getDatetime().toString()); - news_item.put("headline", company_news.getHeadline()); - news_item.put("url", company_news.getUrl()); - news_item.put("summary", company_news.getSummary()); + newsItem.put("category", companyNews.getCategory()); + newsItem.put("datetime", companyNews.getDatetime().toString()); + newsItem.put("headline", companyNews.getHeadline()); + newsItem.put("url", companyNews.getUrl()); + newsItem.put("summary", companyNews.getSummary()); - this.news_items.add(news_item); + this.newsItems.add(newsItem); } + } public String getTicker() {return ticker;} - public List> getNewsItems() {return news_items;} + public List> getNewsItems() {return newsItems;} - // TODO decide whether this is necessary - // public Map getNewsItem(int idx) {return news_items.get(idx);} } \ No newline at end of file diff --git a/src/main/java/view/BuyView.java b/src/main/java/view/BuyView.java index 07d73d9..c5c327e 100644 --- a/src/main/java/view/BuyView.java +++ b/src/main/java/view/BuyView.java @@ -20,6 +20,7 @@ public class BuyView extends JPanel implements ActionListener, PropertyChangeLis public final String viewName = "buy"; private final BuyViewModel buyViewModel; + private final BuyController buyController; private final JLabel amountErrorField = new JLabel(); final JTextField tickerInputField = new JTextField(15); @@ -33,7 +34,7 @@ public class BuyView extends JPanel implements ActionListener, PropertyChangeLis JPanel middlePanel; JPanel bottomPanel; private final JLabel balanceField = new JLabel(); - BuyController buyController; + private void updateBalanceLabelColor() { BuyState state = buyViewModel.getState(); if (state == null || state.getCurBalance() == null || state.getStockInfo() == null) { diff --git a/src/main/java/view/GetNewsView.java b/src/main/java/view/GetNewsView.java index 1f6a47f..2295bc8 100644 --- a/src/main/java/view/GetNewsView.java +++ b/src/main/java/view/GetNewsView.java @@ -1,5 +1,7 @@ package view; +import drivers.TableModel; +import interface_adapters.Buy.BuyState; import interface_adapters.Dashboard.DashboardViewModel; import interface_adapters.GetNews.GetNewsController; import interface_adapters.GetNews.GetNewsState; @@ -25,9 +27,14 @@ public class GetNewsView extends JPanel implements ActionListener, PropertyChang /** * Text fields, labels, and buttons */ - final JTextField tickerIn = new JTextField(4); + final JTextField tickerInputField = new JTextField(5); + private final JLabel tickerErrorField = new JLabel(); + JTable table; final JButton search; final JButton back; + JPanel topPanel; + JPanel middlePanel; + JPanel bottomPanel; public GetNewsView(GetNewsViewModel getNewsViewModel, GetNewsController getNewsController, @@ -40,51 +47,39 @@ public GetNewsView(GetNewsViewModel getNewsViewModel, this.getNewsViewModel = getNewsViewModel; this.getNewsViewModel.addPropertyChangeListener(this); - JLabel title = new JLabel(getNewsViewModel.TITLE_LABEL); - title.setAlignmentX(Component.CENTER_ALIGNMENT); - title.setAlignmentY(Component.TOP_ALIGNMENT); + setPreferredSize(new Dimension(800, 400)); - // Create stock search bar. - LabelTextPanel tickerField = new LabelTextPanel( - new JLabel("Stock ticker"), tickerIn); - tickerField.setAlignmentX(Component.CENTER_ALIGNMENT); - - JPanel back_panel = new JPanel(); back = new JButton(getNewsViewModel.BACK_BUTTON_LABEL); - back_panel.add(back); - - JPanel search_panel = new JPanel(); search = new JButton(getNewsViewModel.SEARCH_BUTTON_LABEL); - search_panel.add(search); + + // Create stock search bar. + LabelTextPanel tickerInput = new LabelTextPanel( + new JLabel("Stock ticker"), tickerInputField); + tickerInput.setAlignmentX(Component.CENTER_ALIGNMENT); back.addActionListener( - new ActionListener() { - public void actionPerformed(ActionEvent evt) { - if (evt.getSource().equals(back)) { - dashboardViewModel.firePropertyChanged(); - viewManagerModel.setActiveView(dashboardViewModel.getViewName()); - viewManagerModel.firePropertyChanged(); - } - } + evt -> { + dashboardViewModel.firePropertyChanged(); + viewManagerModel.setActiveView(dashboardViewModel.getViewName()); + viewManagerModel.firePropertyChanged(); } ); search.addActionListener( - new ActionListener() { - public void actionPerformed(ActionEvent evt) { - if (evt.getSource().equals(search)) { - GetNewsState currentState = getNewsViewModel.getState(); - getNewsController.execute(currentState.getTicker()); - } - } + evt -> { + GetNewsState currentState = getNewsViewModel.getState(); + getNewsController.execute(currentState.getTicker()); + + // TODO: show news items (perhaps not implemented here) + } ); - tickerField.addKeyListener(new KeyListener() { + tickerInput.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { GetNewsState currentState = getNewsViewModel.getState(); - currentState.setTicker(tickerIn.getText() + e.getKeyChar()); + currentState.setTicker(tickerInputField.getText() + e.getKeyChar()); getNewsViewModel.setState(currentState); } @@ -94,12 +89,77 @@ public void keyPressed(KeyEvent e) {} @Override public void keyReleased(KeyEvent e) {} }); - this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - this.add(title); - this.add(tickerField); - this.add(back_panel); - this.add(search_panel); + this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + setLayout(new BorderLayout()); + topPanel = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.WEST; + topPanel.add(back, gbc); + + gbc.gridx = 1; + gbc.weightx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + topPanel.add(Box.createHorizontalGlue(), gbc); + + gbc.gridx = 2; + gbc.weightx = 0; + gbc.fill = GridBagConstraints.NONE; + topPanel.add(tickerInput, gbc); + + gbc.gridx = 3; + gbc.weightx = 0; + topPanel.add(search); + + topPanel.add(tickerErrorField); + + gbc.gridx = 4; + gbc.weightx = 1.24; + topPanel.add(Box.createHorizontalGlue(), gbc); + this.add(topPanel, BorderLayout.NORTH); + + bottomPanel = new JPanel(new GridBagLayout()); + + gbc.gridx = 0; +// bottomPanel.add(amountInput, gbc); + + gbc.gridx = 1; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.EAST; + gbc.weightx = 0; +// bottomPanel.add(balanceField, gbc); + + gbc.gridx = 2; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.EAST; + gbc.weightx = 0; +// purchase.setPreferredSize(new Dimension(350, 40)); +// bottomPanel.add(purchase, gbc); + + + this.add(bottomPanel, BorderLayout.SOUTH); + + middlePanel = new JPanel(new GridBagLayout()); + table = new JTable(); + table.setPreferredSize(new Dimension(100, 200)); +// table.setMinimumSize(new Dimension(100, 100)); + gbc.gridx = 0; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1; +// gbc.weighty = 10000; + middlePanel.add(table, gbc); + add(middlePanel); + + middlePanel.setVisible(false); + bottomPanel.setVisible(false); + +// this.add(tickerInput); +// this.add(back); +// this.add(search); } /** @@ -113,8 +173,28 @@ public void actionPerformed(ActionEvent evt) { public void propertyChange(PropertyChangeEvent evt) { GetNewsState state = (GetNewsState) evt.getNewValue(); setFields(state); + + if (state.getNewsItems() != null && state.getRenderNewInfo() != null) { + table.setModel(new TableModel(state.getNewsItem())); + + middlePanel.setVisible(true); + bottomPanel.setVisible(true); + state.setRenderNewInfo(null); + getNewsViewModel.setState(state); + } + + String tickerError = state.getTickerError(); + + if (tickerError != null) { + JOptionPane.showMessageDialog(this, tickerError); + state.setTickerError(null); + getNewsViewModel.setState(state); + } + } - private void setFields(GetNewsState state) {} + private void setFields(GetNewsState state) { + tickerInputField.setText(state.getTicker()); + } } From e2a1d3594a3234aaffcf28c2a80dd5e2194a5da4 Mon Sep 17 00:00:00 2001 From: quiz3 <113859565+quiz3@users.noreply.github.com> Date: Sun, 26 Nov 2023 18:47:03 -0500 Subject: [PATCH 2/5] GetNewsTable added --- src/main/java/drivers/Finnhub.java | 2 ++ .../use_cases/GetNews/GetNewsInteractor.java | 20 ++++++++-------- src/main/java/view/GetNewsView.java | 24 +++++++------------ 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/main/java/drivers/Finnhub.java b/src/main/java/drivers/Finnhub.java index 2706737..1021a5e 100644 --- a/src/main/java/drivers/Finnhub.java +++ b/src/main/java/drivers/Finnhub.java @@ -108,6 +108,8 @@ public List getCompanyNews(String ticker, LocalDate from, LocalDate String url = "https://finnhub.io/api/v1/company-news?symbol=" + ticker + "&from=" + from + "&to=" + to + "&token=" + APIKEY; + System.out.println(url); + OkHttpClient client = new OkHttpClient().newBuilder() .build(); Request request = new Request.Builder() diff --git a/src/main/java/use_cases/GetNews/GetNewsInteractor.java b/src/main/java/use_cases/GetNews/GetNewsInteractor.java index 88c7c2a..6a745b0 100644 --- a/src/main/java/use_cases/GetNews/GetNewsInteractor.java +++ b/src/main/java/use_cases/GetNews/GetNewsInteractor.java @@ -18,13 +18,13 @@ public GetNewsInteractor(GetNewsOutputBoundary getNewsPresenter, APIAccessInterf @Override public void execute(GetNewsInputData getNewsInputData) { /** - * The getNewsInputData parameter should follow the specifications laid out in that class. - *

- * This method implements the bulk of the GetNews use case. - * News is fetched over a time period of a month prior to the method call. - * - * @param getNewsInputData an InputData object following the relevant CA Engine rules - */ + * The getNewsInputData parameter should follow the specifications laid out in that class. + *

+ * This method implements the bulk of the GetNews use case. + * News is fetched over a time period of a month prior to the method call. + * + * @param getNewsInputData an InputData object following the relevant CA Engine rules + */ String ticker = getNewsInputData.getTicker(); // Define end of news period to be right now @@ -34,15 +34,15 @@ public void execute(GetNewsInputData getNewsInputData) { try { // Make API call - List company_news_list = driverAPI.getCompanyNews(ticker, from, to); + List companyNewsList = driverAPI.getCompanyNews(ticker, from, to); // Save API output using OutputData format for the GetNews use case - GetNewsOutputData result = new GetNewsOutputData(ticker, company_news_list); + GetNewsOutputData result = new GetNewsOutputData(ticker, companyNewsList); getNewsPresenter.prepareSuccessView(result); } catch (RuntimeException e) { -// e.printStackTrace(); + e.printStackTrace(); getNewsPresenter.prepareFailView("Ticker not found or API did not respond."); } } diff --git a/src/main/java/view/GetNewsView.java b/src/main/java/view/GetNewsView.java index 2295bc8..96f74c1 100644 --- a/src/main/java/view/GetNewsView.java +++ b/src/main/java/view/GetNewsView.java @@ -68,6 +68,7 @@ public GetNewsView(GetNewsViewModel getNewsViewModel, search.addActionListener( evt -> { GetNewsState currentState = getNewsViewModel.getState(); + getNewsController.execute(currentState.getTicker()); // TODO: show news items (perhaps not implemented here) @@ -75,7 +76,7 @@ public GetNewsView(GetNewsViewModel getNewsViewModel, } ); - tickerInput.addKeyListener(new KeyListener() { + tickerInputField.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { GetNewsState currentState = getNewsViewModel.getState(); @@ -84,10 +85,14 @@ public void keyTyped(KeyEvent e) { } @Override - public void keyPressed(KeyEvent e) {} + public void keyPressed(KeyEvent e) { + + } @Override - public void keyReleased(KeyEvent e) {} + public void keyReleased(KeyEvent e) { + + } }); this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); @@ -121,26 +126,17 @@ public void keyReleased(KeyEvent e) {} topPanel.add(Box.createHorizontalGlue(), gbc); this.add(topPanel, BorderLayout.NORTH); - bottomPanel = new JPanel(new GridBagLayout()); - gbc.gridx = 0; -// bottomPanel.add(amountInput, gbc); gbc.gridx = 1; gbc.gridy = 0; gbc.anchor = GridBagConstraints.EAST; gbc.weightx = 0; -// bottomPanel.add(balanceField, gbc); gbc.gridx = 2; gbc.gridy = 0; gbc.anchor = GridBagConstraints.EAST; gbc.weightx = 0; -// purchase.setPreferredSize(new Dimension(350, 40)); -// bottomPanel.add(purchase, gbc); - - - this.add(bottomPanel, BorderLayout.SOUTH); middlePanel = new JPanel(new GridBagLayout()); table = new JTable(); @@ -155,11 +151,7 @@ public void keyReleased(KeyEvent e) {} add(middlePanel); middlePanel.setVisible(false); - bottomPanel.setVisible(false); -// this.add(tickerInput); -// this.add(back); -// this.add(search); } /** From 778e74d142f8bb1fb1cc3292d5ace6ccf882053f Mon Sep 17 00:00:00 2001 From: quiz3 <113859565+quiz3@users.noreply.github.com> Date: Sun, 26 Nov 2023 18:51:25 -0500 Subject: [PATCH 3/5] get news view changes finalized with todo to mark what needs to be done --- src/main/java/view/GetNewsView.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/view/GetNewsView.java b/src/main/java/view/GetNewsView.java index 96f74c1..3178a19 100644 --- a/src/main/java/view/GetNewsView.java +++ b/src/main/java/view/GetNewsView.java @@ -34,7 +34,6 @@ public class GetNewsView extends JPanel implements ActionListener, PropertyChang final JButton back; JPanel topPanel; JPanel middlePanel; - JPanel bottomPanel; public GetNewsView(GetNewsViewModel getNewsViewModel, GetNewsController getNewsController, @@ -70,9 +69,6 @@ public GetNewsView(GetNewsViewModel getNewsViewModel, GetNewsState currentState = getNewsViewModel.getState(); getNewsController.execute(currentState.getTicker()); - - // TODO: show news items (perhaps not implemented here) - } ); @@ -170,9 +166,12 @@ public void propertyChange(PropertyChangeEvent evt) { table.setModel(new TableModel(state.getNewsItem())); middlePanel.setVisible(true); - bottomPanel.setVisible(true); state.setRenderNewInfo(null); getNewsViewModel.setState(state); + + // TODO: fix this property change so that the table is scrollable, + // allowing the user to see multiple news items + } String tickerError = state.getTickerError(); From 2485f84077ad259304826307db206ecd2061053b Mon Sep 17 00:00:00 2001 From: quiz3 <113859565+quiz3@users.noreply.github.com> Date: Sun, 26 Nov 2023 19:43:31 -0500 Subject: [PATCH 4/5] Table added to the get news view --- src/main/java/view/GetNewsView.java | 34 ++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/main/java/view/GetNewsView.java b/src/main/java/view/GetNewsView.java index 3178a19..925d068 100644 --- a/src/main/java/view/GetNewsView.java +++ b/src/main/java/view/GetNewsView.java @@ -1,7 +1,9 @@ package view; +import java.util.Map; +import java.util.List; + import drivers.TableModel; -import interface_adapters.Buy.BuyState; import interface_adapters.Dashboard.DashboardViewModel; import interface_adapters.GetNews.GetNewsController; import interface_adapters.GetNews.GetNewsState; @@ -14,6 +16,8 @@ import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; +import java.awt.BorderLayout; +import java.awt.Dimension; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -34,6 +38,8 @@ public class GetNewsView extends JPanel implements ActionListener, PropertyChang final JButton back; JPanel topPanel; JPanel middlePanel; + JTabbedPane newsTabs; + ImageIcon icon; public GetNewsView(GetNewsViewModel getNewsViewModel, GetNewsController getNewsController, @@ -135,15 +141,15 @@ public void keyReleased(KeyEvent e) { gbc.weightx = 0; middlePanel = new JPanel(new GridBagLayout()); - table = new JTable(); - table.setPreferredSize(new Dimension(100, 200)); -// table.setMinimumSize(new Dimension(100, 100)); + newsTabs = new JTabbedPane(); + icon = new ImageIcon("images/news.png"); + gbc.gridx = 0; gbc.gridy = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1; // gbc.weighty = 10000; - middlePanel.add(table, gbc); + middlePanel.add(newsTabs, gbc); add(middlePanel); middlePanel.setVisible(false); @@ -162,16 +168,24 @@ public void propertyChange(PropertyChangeEvent evt) { GetNewsState state = (GetNewsState) evt.getNewValue(); setFields(state); - if (state.getNewsItems() != null && state.getRenderNewInfo() != null) { - table.setModel(new TableModel(state.getNewsItem())); + List> newsItems = state.getNewsItems(); + + if (newsItems != null && state.getRenderNewInfo() != null) { + + for (int i = 0; i < 5; i++) { + Map newsItem = newsItems.get(i); + + JTable table = new JTable(); + table.setPreferredSize(new Dimension(100, 200)); + table.setModel(new TableModel(newsItem)); + + newsTabs.addTab(String.format("Article %d", i + 1), icon, table); + } middlePanel.setVisible(true); state.setRenderNewInfo(null); getNewsViewModel.setState(state); - // TODO: fix this property change so that the table is scrollable, - // allowing the user to see multiple news items - } String tickerError = state.getTickerError(); From e9e86f57adb997291a0dd4b83e24845cb8e9a44c Mon Sep 17 00:00:00 2001 From: quiz3 <113859565+quiz3@users.noreply.github.com> Date: Sun, 26 Nov 2023 19:46:34 -0500 Subject: [PATCH 5/5] cleaned up evidence of debugging --- src/main/java/drivers/Finnhub.java | 2 -- src/main/java/use_cases/GetNews/GetNewsInteractor.java | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/drivers/Finnhub.java b/src/main/java/drivers/Finnhub.java index 1021a5e..2706737 100644 --- a/src/main/java/drivers/Finnhub.java +++ b/src/main/java/drivers/Finnhub.java @@ -108,8 +108,6 @@ public List getCompanyNews(String ticker, LocalDate from, LocalDate String url = "https://finnhub.io/api/v1/company-news?symbol=" + ticker + "&from=" + from + "&to=" + to + "&token=" + APIKEY; - System.out.println(url); - OkHttpClient client = new OkHttpClient().newBuilder() .build(); Request request = new Request.Builder() diff --git a/src/main/java/use_cases/GetNews/GetNewsInteractor.java b/src/main/java/use_cases/GetNews/GetNewsInteractor.java index 6a745b0..ed1bc69 100644 --- a/src/main/java/use_cases/GetNews/GetNewsInteractor.java +++ b/src/main/java/use_cases/GetNews/GetNewsInteractor.java @@ -42,7 +42,7 @@ public void execute(GetNewsInputData getNewsInputData) { getNewsPresenter.prepareSuccessView(result); } catch (RuntimeException e) { - e.printStackTrace(); +// e.printStackTrace(); getNewsPresenter.prepareFailView("Ticker not found or API did not respond."); } }