<commit_before>//=======================================================================
// Copyright <NAME> 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "report.hpp"
#include "expenses.hpp"
#include "earnings.hpp"
#include "budget_exception.hpp"
#include "accounts.hpp"

using namespace budget;

namespace {

typedef std::vector<std::vector<std::string>> graph_type;

void render(graph_type& graph){
    std::reverse(graph.begin(), graph.end());

    for(auto& line : graph){
        for(auto& col : line){
            std::cout << col;
        }
        std::cout << std::endl;
    }
}

void write(graph_type& graph, int row, int col, const std::string& value){
    for(std::size_t i = 0; i < value.size(); ++i){
        graph[row][col + i] = value[i];
    }
}

void monthly_report(boost::gregorian::greg_year year){
    auto today = boost::gregorian::day_clock::local_day();

    budget::money max_expenses;
    budget::money max_earnings;
    budget::money max_balance;
    budget::money min_expenses;
    budget::money min_earnings;
    budget::money min_balance;

    auto sm = start_month(year);

    std::vector<int> expenses(13);
    std::vector<int> earnings(13);
    std::vector<int> balances(13);

    for(unsigned short i = sm + 1; i < today.month() + 1; ++i){
        boost::gregorian::greg_month month = i;

        auto accounts = all_accounts(year, month);

        budget::money total_expenses;
        budget::money total_earnings;
        budget::money total_balance;

        for(auto& account : accounts){
            auto expenses = accumulate_amount_if(all_expenses(),
                [year,month,account](budget::expense& e){return e.account == account.id && e.date.year() == year && e.date.month() == month;});
            auto earnings = accumulate_amount_if(all_earnings(),
                [year,month,account](budget::earning& e){return e.account == account.id && e.date.year() == year && e.date.month() == month;});

            total_expenses += expenses;
            total_earnings += earnings;

            auto balance = account.amount;
            balance -= expenses;
            balance += earnings;

            total_balance += balance;
        }

        expenses[month] = total_expenses.dollars();
        earnings[month] = total_earnings.dollars();
        balances[month] = total_balance.dollars();

        max_expenses = std::max(max_expenses, total_expenses);
        max_earnings = std::max(max_earnings, total_earnings);
        max_balance = std::max(max_balance, total_balance);
        min_expenses = std::min(min_expenses, total_expenses);
        min_earnings = std::min(min_earnings, total_earnings);
        min_balance = std::min(min_balance, total_balance);
    }

    auto height = terminal_height() - 9;
    auto width = terminal_width() - 6;

    //TODO compute the scale based on the data
    unsigned int scale = 1000;

    int min = 0;
    if(min_expenses.negative() || min_earnings.negative() || min_balance.negative()){
        min = std::min(min_expenses, std::min(min_earnings, min_balance)).dollars();
        min = -1 * ((std::abs(min) / scale) + 1) * scale;
    }

    unsigned int max = std::max(max_earnings, std::max(max_expenses, max_balance)).dollars();
    max = ((max / scale) + 1) * scale;

    unsigned int levels = max / scale + std::abs(min) / scale;

    unsigned int step_height = height / levels;
    unsigned int precision = scale / step_height;

    auto graph_height = 9 + step_height * levels;
    auto graph_width = 6 + (12 - sm) * 8 + (12 - sm - 1) * 2;

    graph_type graph(graph_height, std::vector<std::string>(graph_width, " "));

    write(graph, graph_height - 2, 8, "Monthly report of " + to_string(year));

    unsigned int min_index = 3;
    unsigned int zero_index = min_index + 1 + (std::abs(min) / scale) * step_height;

    for(unsigned short i = sm + 1; i < today.month() + 1; ++i){
        boost::gregorian::greg_month month = i;<commit_msg>Display scale<commit_after>//=======================================================================
// Copyright <NAME> 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "report.hpp"
#include "expenses.hpp"
#include "earnings.hpp"
#include "budget_exception.hpp"
#include "accounts.hpp"

using namespace budget;

namespace {

typedef std::vector<std::vector<std::string>> graph_type;

void render(graph_type& graph){
    std::reverse(graph.begin(), graph.end());

    for(auto& line : graph){
        for(auto& col : line){
            std::cout << col;
        }
        std::cout << std::endl;
    }
}

void write(graph_type& graph, int row, int col, const std::string& value){
    for(std::size_t i = 0; i < value.size(); ++i){
        graph[row][col + i] = value[i];
    }
}

void monthly_report(boost::gregorian::greg_year year){
    auto today = boost::gregorian::day_clock::local_day();

    budget::money max_expenses;
    budget::money max_earnings;
    budget::money max_balance;
    budget::money min_expenses;
    budget::money min_earnings;
    budget::money min_balance;

    auto sm = start_month(year);

    std::vector<int> expenses(13);
    std::vector<int> earnings(13);
    std::vector<int> balances(13);

    for(unsigned short i = sm + 1; i < today.month() + 1; ++i){
        boost::gregorian::greg_month month = i;

        auto accounts = all_accounts(year, month);

        budget::money total_expenses;
        budget::money total_earnings;
        budget::money total_balance;

        for(auto& account : accounts){
            auto expenses = accumulate_amount_if(all_expenses(),
                [year,month,account](budget::expense& e){return e.account == account.id && e.date.year() == year && e.date.month() == month;});
            auto earnings = accumulate_amount_if(all_earnings(),
                [year,month,account](budget::earning& e){return e.account == account.id && e.date.year() == year && e.date.month() == month;});

            total_expenses += expenses;
            total_earnings += earnings;

            auto balance = account.amount;
            balance -= expenses;
            balance += earnings;

            total_balance += balance;
        }

        expenses[month] = total_expenses.dollars();
        earnings[month] = total_earnings.dollars();
        balances[month] = total_balance.dollars();

        max_expenses = std::max(max_expenses, total_expenses);
        max_earnings = std::max(max_earnings, total_earnings);
        max_balance = std::max(max_balance, total_balance);
        min_expenses = std::min(min_expenses, total_expenses);
        min_earnings = std::min(min_earnings, total_earnings);
        min_balance = std::min(min_balance, total_balance);
    }

    auto height = terminal_height() - 9;
    auto width = terminal_width() - 6;

    //TODO compute the scale based on the data
    unsigned int scale = 1000;

    int min = 0;
    if(min_expenses.negative() || min_earnings.negative() || min_balance.negative()){
        min = std::min(min_expenses, std::min(min_earnings, min_balance)).dollars();
        min = -1 * ((std::abs(min) / scale) + 1) * scale;
    }

    unsigned int max = std::max(max_earnings, std::max(max_expenses, max_balance)).dollars();
    max = ((max / scale) + 1) * scale;

    unsigned int levels = max / scale + std::abs(min) / scale;

    unsigned int step_height = height / levels;
    unsigned int precision = scale / step_height;

    auto graph_height = 9 + step_height * levels;
    auto graph_width = 6 + (12 - sm) * 8 + (12 - sm - 1) * 2;

    graph_type graph(graph_height, std::vector<std::string>(graph_width, " "));

    //Display graph title

    write(graph, graph_height - 2, 8, "Monthly report of " + to_string(year));

    //Display scale

    int first_step = min == 0 ? 0 : -1 * ((-min % scale) + 1) * scale;

    for(int i = 0; i <= levels; ++i){
        int level = first_step + i * scale;

        write(graph, 4 + step_height * i, 1, to_string(level));
    }

    //Display bar

    unsigned int min_index = 3;
    unsigned int zero_index = min_index + 1 + (std::abs(min) / scale) * step_height;

    for(unsigned short i = sm + 1; i < today.month() + 1; ++i){
        boost::gregorian::greg_month month = i;
{'fraction_non_alphanumeric': 0.17355371900826447, 'fraction_numerical': 0.011058084041438715, 'mean_word_length': 3.1547388781431334, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '6668027', 'n_tokens_mistral': 2796, 'n_tokens_neox': 2619, 'n_words': 626}