<commit_before>/**
 * Copyright 2016 <NAME>.  Distributed under the MIT license.
 */
#include <wx/wx.h>
#include <wx/sizer.h>
#include <greentop/ExchangeApi.h>
#include <greentop/sport/enum/MarketStatus.h>
#include <greentop/sport/enum/RunnerStatus.h>

#include "dialog/PlaceBet.h"
#include "entity/Config.h"
#include "worker/CancelOrders.h"
#include "worker/ListCurrentOrders.h"
#include "worker/PlaceOrders.h"
#include "worker/ReplaceOrders.h"

#include "MarketPanel.h"
#include "RunnerRow.h"
#include "Util.h"

namespace greenthumb {

MarketPanel::MarketPanel(MarketPanels* parent, const wxWindowID id, const wxPoint& pos,
    const wxSize& size, long style, const wxString& name) :
    wxPanel(parent, id, pos, size, style, name), refreshTimer(this, wxID_ANY), workerManager(this) {

    marketPanels = parent;

    wxBoxSizer* tbSizer = new wxBoxSizer(wxVERTICAL);
    SetSizer(tbSizer);

    marketToolbar = new MarketToolbar(this, wxID_ANY);
    marketToolbar->Bind(wxEVT_BUTTON, &MarketPanel::OnClickClose, this, marketToolbar->GetCloseButtonId());
    marketToolbar->Bind(wxEVT_BUTTON, &MarketPanel::RefreshPrices, this, marketToolbar->GetRefreshButtonId());
    marketToolbar->Bind(wxEVT_BUTTON, &MarketPanel::ShowCurrentOrders, this, marketToolbar->GetCurrentOrdersButtonId());
    tbSizer->Add(marketToolbar, 0, wxEXPAND);

    pricesPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);

    wxFlexGridSizer* sizer = new wxFlexGridSizer(10);
    sizer->AddGrowableCol(1, 1);
    pricesPanel->SetSizer(sizer);

    tbSizer->Add(pricesPanel, 0, wxEXPAND);

    refreshTimer.Start(entity::Config::GetConfigValue("marketRefreshSec", 60) * 1000);

    currentOrdersDialog = new dialog::CurrentOrders(this, wxID_ANY, "Current Bets");

    Bind(worker::LIST_MARKET_BOOK, &MarketPanel::OnMarketUpdated, this);
    workerManager.Bind(worker::LIST_MARKET_BOOK);
    Bind(worker::LIST_MARKET_PROFIT_AND_LOSS, &MarketPanel::OnListMarketProfitAndLoss, this);
    workerManager.Bind(worker::LIST_MARKET_PROFIT_AND_LOSS);
    Bind(worker::PLACE_ORDERS, &MarketPanel::OnPlaceBet, this);
    Bind(worker::CANCEL_ORDERS, &MarketPanel::OnCancelOrders, this);
    Bind(wxEVT_TIMER, &MarketPanel::RefreshPrices, this);
    Bind(dialog::PLACE_ORDER_PENDING, &MarketPanel::OnPlaceOrderPending, this);
    Bind(worker::LIST_CURRENT_ORDERS, &MarketPanel::OnListCurrentOrders, this, wxID_ANY);
    Bind(worker::REPLACE_ORDERS, &MarketPanel::RefreshPrices, this, wxID_ANY);
}

void MarketPanel::OnMarketUpdated(const wxThreadEvent& event) {

    greentop::MarketBook tempMarketBook = event.GetPayload<greentop::MarketBook>();

    if (tempMarketBook.isValid()) {
        marketBook = tempMarketBook;

        SyncRunnerRows();

        if (marketBook.getStatus() == greentop::MarketStatus::OPEN ||
            marketBook.getStatus() == greentop::MarketStatus::SUSPENDED) {
            refreshTimer.Start();
        } else {
            refreshTimer.Stop();
        }

        worker::ListMarketProfitAndLoss* listMarketProfitAndLossWorker =
            new worker::ListMarketProfitAndLoss(&workerManager, market.GetExchange(),
                market.GetMarketCatalogue().getMarketId());
        workerManager.RunWorker(listMarketProfitAndLossWorker);

        UpdateToolBar();
        UpdateMarketStatus();
    }
}

void MarketPanel::OnListMarketProfitAndLoss(const wxThreadEvent& event) {

    currentOrdersDialog->Refresh();

    greentop::ListMarketProfitAndLossResponse lmpalr = event.GetPayload<greentop::ListMarketProfitAndLossResponse>();

    if (lmpalr.isSuccess()) {
        std::vector<greentop::MarketProfitAndLoss> marketProfitAndLosses = lmpalr.getMarketProfitAndLosses();

        std::vector<greentop::MarketProfitAndLoss>::iterator it1;
        for (it1 = marketProfitAndLosses.begin(); it1 != marketProfitAndLosses.end(); ++it1) {

            greentop::MarketProfitAndLoss marketProfitAndLoss = *it1;

            if (marketProfitAndLoss.getMarketId() == market.GetMarketCatalogue().getMarketId()) {

                std::vector<greentop::RunnerProfitAndLoss> profitAndLosses = marketProfitAndLoss.getProfitAndLosses();

                std::vector<greentop::RunnerProfitAndLoss>::iterator it2;
                for (it2 = profitAndLosses.begin(); it2 != profitAndLosses.end(); ++it2) {
                    greentop::RunnerProfitAndLoss runnerProfitAndLoss = *it2;
                    if (runnerRows.find(runnerProfitAndLoss.getSelectionId()) != runnerRows.end()) {
                        greentop::Optional<double> optionalIfWin = runnerProfitAndLoss.getIfWin();
                        double ifWin = 0;
                        if (optionalIfWin.isValid()) {
                            ifWin = optionalIfWin.getValue();
                        }
                        runnerRows[runnerProfitAndLoss.getSelectionId()]->SetProfit(ifWin);
                    }
                }
            }
        }

        GetParent()->Layout();
    }
}

void MarketPanel::RefreshPrices() {
    worker::ListMarketBook* listMarketBookThread = new worker::ListMarketBook(&workerManager, market);
    workerManager.RunWorker(listMarketBookThread);
}

void MarketPanel::RefreshPrices(const wxEvent& event) {
    RefreshPrices();
}

void MarketPanel::SetMarket(const greentop::menu::Node& node) {

    marketId = node.getId();
    std::tm marketStartTime = node.getMarketStartTime();
    time_t startTime = timegm(&marketStartTime);
    char formattedStartTime[20];
    std::strftime(formattedStartTime, 20, "%F %T", std::localtime(&startTime));

    if (node.hasParent()) {
        fullMarketName = node.getParent().getName() + " / " + node.getName();
        std::string title = fullMarketName + " / " + formattedStartTime;
        wxString label(title.c_str(), wxConvUTF8);
        currentOrdersDialog->SetTitle(fullMarketName);
        marketToolbar->SetMarketName(label);
    }

}

void MarketPanel::SetMarket(const entity::Market& market) {

    this->market = market;
    marketId = market.GetMarketCatalogue().getMarketId();

    SyncRunnerRows();
    RefreshPrices();

    Bind(wxEVT_BUTTON, &MarketPanel::OnClick, this, wxID_ANY);<commit_msg>strftime() doesn't support %F and %T under MinGW.  Microsoft's docs make no mention of these, but they do work with Visual Studio.<commit_after>/**
 * Copyright 2016 <NAME>.  Distributed under the MIT license.
 */
#include <wx/wx.h>
#include <wx/sizer.h>
#include <greentop/ExchangeApi.h>
#include <greentop/sport/enum/MarketStatus.h>
#include <greentop/sport/enum/RunnerStatus.h>

#include "dialog/PlaceBet.h"
#include "entity/Config.h"
#include "worker/CancelOrders.h"
#include "worker/ListCurrentOrders.h"
#include "worker/PlaceOrders.h"
#include "worker/ReplaceOrders.h"

#include "MarketPanel.h"
#include "RunnerRow.h"
#include "Util.h"

namespace greenthumb {

MarketPanel::MarketPanel(MarketPanels* parent, const wxWindowID id, const wxPoint& pos,
    const wxSize& size, long style, const wxString& name) :
    wxPanel(parent, id, pos, size, style, name), refreshTimer(this, wxID_ANY), workerManager(this) {

    marketPanels = parent;

    wxBoxSizer* tbSizer = new wxBoxSizer(wxVERTICAL);
    SetSizer(tbSizer);

    marketToolbar = new MarketToolbar(this, wxID_ANY);
    marketToolbar->Bind(wxEVT_BUTTON, &MarketPanel::OnClickClose, this, marketToolbar->GetCloseButtonId());
    marketToolbar->Bind(wxEVT_BUTTON, &MarketPanel::RefreshPrices, this, marketToolbar->GetRefreshButtonId());
    marketToolbar->Bind(wxEVT_BUTTON, &MarketPanel::ShowCurrentOrders, this, marketToolbar->GetCurrentOrdersButtonId());
    tbSizer->Add(marketToolbar, 0, wxEXPAND);

    pricesPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);

    wxFlexGridSizer* sizer = new wxFlexGridSizer(10);
    sizer->AddGrowableCol(1, 1);
    pricesPanel->SetSizer(sizer);

    tbSizer->Add(pricesPanel, 0, wxEXPAND);

    refreshTimer.Start(entity::Config::GetConfigValue("marketRefreshSec", 60) * 1000);

    currentOrdersDialog = new dialog::CurrentOrders(this, wxID_ANY, "Current Bets");

    Bind(worker::LIST_MARKET_BOOK, &MarketPanel::OnMarketUpdated, this);
    workerManager.Bind(worker::LIST_MARKET_BOOK);
    Bind(worker::LIST_MARKET_PROFIT_AND_LOSS, &MarketPanel::OnListMarketProfitAndLoss, this);
    workerManager.Bind(worker::LIST_MARKET_PROFIT_AND_LOSS);
    Bind(worker::PLACE_ORDERS, &MarketPanel::OnPlaceBet, this);
    Bind(worker::CANCEL_ORDERS, &MarketPanel::OnCancelOrders, this);
    Bind(wxEVT_TIMER, &MarketPanel::RefreshPrices, this);
    Bind(dialog::PLACE_ORDER_PENDING, &MarketPanel::OnPlaceOrderPending, this);
    Bind(worker::LIST_CURRENT_ORDERS, &MarketPanel::OnListCurrentOrders, this, wxID_ANY);
    Bind(worker::REPLACE_ORDERS, &MarketPanel::RefreshPrices, this, wxID_ANY);
}

void MarketPanel::OnMarketUpdated(const wxThreadEvent& event) {

    greentop::MarketBook tempMarketBook = event.GetPayload<greentop::MarketBook>();

    if (tempMarketBook.isValid()) {
        marketBook = tempMarketBook;

        SyncRunnerRows();

        if (marketBook.getStatus() == greentop::MarketStatus::OPEN ||
            marketBook.getStatus() == greentop::MarketStatus::SUSPENDED) {
            refreshTimer.Start();
        } else {
            refreshTimer.Stop();
        }

        worker::ListMarketProfitAndLoss* listMarketProfitAndLossWorker =
            new worker::ListMarketProfitAndLoss(&workerManager, market.GetExchange(),
                market.GetMarketCatalogue().getMarketId());
        workerManager.RunWorker(listMarketProfitAndLossWorker);

        UpdateToolBar();
        UpdateMarketStatus();
    }
}

void MarketPanel::OnListMarketProfitAndLoss(const wxThreadEvent& event) {

    currentOrdersDialog->Refresh();

    greentop::ListMarketProfitAndLossResponse lmpalr = event.GetPayload<greentop::ListMarketProfitAndLossResponse>();

    if (lmpalr.isSuccess()) {
        std::vector<greentop::MarketProfitAndLoss> marketProfitAndLosses = lmpalr.getMarketProfitAndLosses();

        std::vector<greentop::MarketProfitAndLoss>::iterator it1;
        for (it1 = marketProfitAndLosses.begin(); it1 != marketProfitAndLosses.end(); ++it1) {

            greentop::MarketProfitAndLoss marketProfitAndLoss = *it1;

            if (marketProfitAndLoss.getMarketId() == market.GetMarketCatalogue().getMarketId()) {

                std::vector<greentop::RunnerProfitAndLoss> profitAndLosses = marketProfitAndLoss.getProfitAndLosses();

                std::vector<greentop::RunnerProfitAndLoss>::iterator it2;
                for (it2 = profitAndLosses.begin(); it2 != profitAndLosses.end(); ++it2) {
                    greentop::RunnerProfitAndLoss runnerProfitAndLoss = *it2;
                    if (runnerRows.find(runnerProfitAndLoss.getSelectionId()) != runnerRows.end()) {
                        greentop::Optional<double> optionalIfWin = runnerProfitAndLoss.getIfWin();
                        double ifWin = 0;
                        if (optionalIfWin.isValid()) {
                            ifWin = optionalIfWin.getValue();
                        }
                        runnerRows[runnerProfitAndLoss.getSelectionId()]->SetProfit(ifWin);
                    }
                }
            }
        }

        GetParent()->Layout();
    }
}

void MarketPanel::RefreshPrices() {
    worker::ListMarketBook* listMarketBookThread = new worker::ListMarketBook(&workerManager, market);
    workerManager.RunWorker(listMarketBookThread);
}

void MarketPanel::RefreshPrices(const wxEvent& event) {
    RefreshPrices();
}

void MarketPanel::SetMarket(const greentop::menu::Node& node) {

    marketId = node.getId();
    std::tm marketStartTime = node.getMarketStartTime();
    time_t startTime = timegm(&marketStartTime);
    char formattedStartTime[20];
    std::strftime(formattedStartTime, 20, "%Y-%m-%d %H:%M:%S", std::localtime(&startTime));

    if (node.hasParent()) {
        fullMarketName = node.getParent().getName() + " / " + node.getName();
        std::string title = fullMarketName + " / " + formattedStartTime;
        wxString label(title.c_str(), wxConvUTF8);
        currentOrdersDialog->SetTitle(fullMarketName);
        marketToolbar->SetMarketName(label);
    }

}

void MarketPanel::SetMarket(const entity::Market& market) {

    this->market = market;
    marketId = market.GetMarketCatalogue().getMarketId();

    SyncRunnerRows();
    RefreshPrices();

    Bind(wxEVT_BUTTON, &MarketPanel::OnClick, this, wxID_ANY);
{'fraction_non_alphanumeric': 0.12492988220209952, 'fraction_numerical': 0.00512861607500601, 'mean_word_length': 4.038352846184901, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1958521', 'n_tokens_mistral': 4099, 'n_tokens_neox': 3797, 'n_words': 598}