<commit_before>#include <utility>
#include <SFML/Graphics.hpp>

#include "menu.hpp"

void gui::Menu::generateGeometry()
{
	// First split each entry into lines which fit within the desired bounds
	std::vector<std::vector<std::string>> alignedEntries;
	for(auto entry : entries)
		alignedEntries.push_back(gui::alignString(entry.first, entrySize.x));

	// If laid out from left to right and top to bottom, then the
	// quotient of (number of entries) / (entries per row) will give
	// the number of completed rows, and the remainder will give the
	// number of entries on the partially completed row.
	unsigned int numRows = entries.size() / alignment.x;
	unsigned int partialRow = entries.size() % alignment.x;
	// We now concatenate the first entrySize.y lines of each
	// group of alignment.x entries. As an example if alignment is (3,1)
	// and entrySize is (5, 2) we will transform
	// {
	// 		{"opt1"},
	// 		{"opti2","line2"},
	// 		{"op3", "line2", "line3"}
	// }
	// to
	// {
	// 		{" opt1  ", "       "},
	// 		{" opti2 ", " line2 "},
	// 		{" op3   ", " line2 ", " line3 "}
	// }
	// and then to
	// {
	// 		{" opt1   opti2  op3   "},
	// 		{"        line2  line2 "}
	// }
	// Note that we will also add the correct padding, and will discard any
	// text outside of the bounds (if each entry were a messagebox, they would
	// be on another page).
	for(auto& entry : alignedEntries)
	{
		// First pad the existing rows
		for(size_t row = 0; row < entry.size(); ++row)
		{
			// Far left and right padding is 1, internal padding is 2,
			// which is equivalent to each entry being surrounded by 1
			// space. Each entry should also have additional right padding
			// so that it's the same length as entrySize.x
			entry[row] = " " + entry[row] + std::string(1 + entrySize.x - entry[row].size(), ' ');
		}
		// Now add additional rows made of whitespace, if necessary
		for(size_t row = entry.size(); row < entrySize.y; ++row)
		{
			entry.push_back(std::string(entrySize.x + 2, ' '));
		}
	}
	// Now each entry is padded, they can be combined
	std::vector<std::string> alignedLines;
	// Note row is not a line, but rather a row of entries
	// which may span multiple lines
	for(unsigned int row = 0; row < numRows; ++row)
	{
		for(unsigned int line = 0; line < entrySize.y; ++line)
		{
			std::string alignedLine;
			for(unsigned int entry = 0; entry < alignment.x; ++entry)
			{
				alignedLine += alignedEntries[row * alignment.x + entry][line];
			}
			alignedLines.push_back(alignedLine);
		}
	}
	// Now do the last partial row, if there is one
	// if(partialRow > 0)
	// {
	// 	for(unsigned int line = 0; line < entrySize.y; ++line)
	// 	{
	// 		std::string alignedLine;
	// 		for(unsigned int entry = 0; entry < partialRow; ++entry)
	// 		{
	// 			alignedLine += alignedEntries[(numRows-1) * alignment.x + entry][line];
	// 		}
	// 	}
	// }

	// Width and height of final text, without borders
	unsigned int width = alignment.x * (entrySize.x + 2);
	unsigned int height = alignment.y * entrySize.y;

	// Add top border
	std::string textStr = "\x80" + std::string(width, '\x87') + "\x81\n";

	// Add entry lines, up to the maximum number allowable
	unsigned int bound = alignedLines.size();
	if(bound > height) bound = height;
	for(unsigned int i = 0; i < bound; ++i)
	{
		textStr += "\x86" + alignedLines[i] + "\x84\n";
	}

	// Add padding lines, up to the indented height
	std::string padding(width, ' ');
	for(unsigned int i = bound; i < height; ++i)
	{
		textStr += "\x86" + padding + "\x84\n";
	}

	// Add bottom border
	textStr += "\x83" + std::string(width, '\x85') + "\x82";

	// Finally we can create the gui::Text
	text = gui::Text(textStr, *font);
}<commit_msg>Partial row at the end of the gui::menu is now added correctly<commit_after>#include <utility>
#include <SFML/Graphics.hpp>

#include "menu.hpp"

void gui::Menu::generateGeometry()
{
	// First split each entry into lines which fit within the desired bounds
	std::vector<std::vector<std::string>> alignedEntries;
	for(auto entry : entries)
		alignedEntries.push_back(gui::alignString(entry.first, entrySize.x));

	// If laid out from left to right and top to bottom, then the
	// quotient of (number of entries) / (entries per row) will give
	// the number of completed rows, and the remainder will give the
	// number of entries on the partially completed row.
	unsigned int numRows = entries.size() / alignment.x;
	unsigned int partialRow = entries.size() % alignment.x;
	// We now concatenate the first entrySize.y lines of each
	// group of alignment.x entries. As an example if alignment is (3,1)
	// and entrySize is (5, 2) we will transform
	// {
	// 		{"opt1"},
	// 		{"opti2","line2"},
	// 		{"op3", "line2", "line3"}
	// }
	// to
	// {
	// 		{" opt1  ", "       "},
	// 		{" opti2 ", " line2 "},
	// 		{" op3   ", " line2 ", " line3 "}
	// }
	// and then to
	// {
	// 		{" opt1   opti2  op3   "},
	// 		{"        line2  line2 "}
	// }
	// Note that we will also add the correct padding, and will discard any
	// text outside of the bounds (if each entry were a messagebox, they would
	// be on another page).
	for(auto& entry : alignedEntries)
	{
		// First pad the existing rows
		for(size_t row = 0; row < entry.size(); ++row)
		{
			// Far left and right padding is 1, internal padding is 2,
			// which is equivalent to each entry being surrounded by 1
			// space. Each entry should also have additional right padding
			// so that it's the same length as entrySize.x
			entry[row] = " " + entry[row] + std::string(1 + entrySize.x - entry[row].size(), ' ');
		}
		// Now add additional rows made of whitespace, if necessary
		for(size_t row = entry.size(); row < entrySize.y; ++row)
		{
			entry.push_back(std::string(entrySize.x + 2, ' '));
		}
	}
	// Now each entry is padded, they can be combined
	std::vector<std::string> alignedLines;
	// Note row is not a line, but rather a row of entries
	// which may span multiple lines
	for(unsigned int row = 0; row < numRows; ++row)
	{
		for(unsigned int line = 0; line < entrySize.y; ++line)
		{
			std::string alignedLine;
			for(unsigned int entry = 0; entry < alignment.x; ++entry)
			{
				alignedLine += alignedEntries[row * alignment.x + entry][line];
			}
			alignedLines.push_back(alignedLine);
		}
	}
	// Now do the last partial row, if there is one
	if(partialRow > 0)
	{
		for(unsigned int line = 0; line < entrySize.y; ++line)
		{
			std::string alignedLine;
			for(unsigned int entry = 0; entry < partialRow; ++entry)
			{
				alignedLine += alignedEntries[numRows * alignment.x + entry][line];
			}
			alignedLine += std::string((alignment.x-partialRow) * (2+entrySize.x), ' ');
			alignedLines.push_back(alignedLine);
		}
	}

	// Width and height of final text, without borders
	unsigned int width = alignment.x * (entrySize.x + 2);
	unsigned int height = alignment.y * entrySize.y;

	// Add top border
	std::string textStr = "\x80" + std::string(width, '\x87') + "\x81\n";

	// Add entry lines, up to the maximum number allowable
	unsigned int bound = alignedLines.size();
	if(bound > height) bound = height;
	for(unsigned int i = 0; i < bound; ++i)
	{
		textStr += "\x86" + alignedLines[i] + "\x84\n";
	}

	// Add padding lines, up to the indented height
	std::string padding(width, ' ');
	for(unsigned int i = bound; i < height; ++i)
	{
		textStr += "\x86" + padding + "\x84\n";
	}

	// Add bottom border
	textStr += "\x83" + std::string(width, '\x85') + "\x82";

	// Finally we can create the gui::Text
	text = gui::Text(textStr, *font);
}
{'fraction_non_alphanumeric': 0.15027977617905675, 'fraction_numerical': 0.014921396216360246, 'mean_word_length': 3.001599147121535, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 17, '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': '1951545', 'n_tokens_mistral': 2718, 'n_tokens_neox': 2522, 'n_words': 841}