mirror of
https://github.com/koloideal/SortLab.git
synced 2026-06-10 10:25:30 +03:00
skelet
This commit is contained in:
@@ -22,6 +22,7 @@ add_executable(SortLab
|
|||||||
src/Array.cpp
|
src/Array.cpp
|
||||||
src/Sorter.cpp
|
src/Sorter.cpp
|
||||||
src/UI.cpp
|
src/UI.cpp
|
||||||
|
src/OperationsHistory.cpp
|
||||||
src/sorters/BubbleSorter.cpp
|
src/sorters/BubbleSorter.cpp
|
||||||
src/sorters/SelectionSorter.cpp
|
src/sorters/SelectionSorter.cpp
|
||||||
src/sorters/InsertionSorter.cpp
|
src/sorters/InsertionSorter.cpp
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "Array.hpp"
|
#include "Array.hpp"
|
||||||
#include "Sorter.hpp"
|
#include "Sorter.hpp"
|
||||||
#include "UI.hpp"
|
#include "UI.hpp"
|
||||||
|
#include "OperationsHistory.hpp"
|
||||||
|
|
||||||
class App {
|
class App {
|
||||||
public:
|
public:
|
||||||
@@ -15,6 +16,7 @@ private:
|
|||||||
void handleEvents();
|
void handleEvents();
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
void render();
|
void render();
|
||||||
|
void renderHistogram();
|
||||||
void switchSorter(std::unique_ptr<Sorter> newSorter);
|
void switchSorter(std::unique_ptr<Sorter> newSorter);
|
||||||
void generateBeepSound();
|
void generateBeepSound();
|
||||||
void playBeep(float pitch);
|
void playBeep(float pitch);
|
||||||
@@ -23,6 +25,7 @@ private:
|
|||||||
Array array_;
|
Array array_;
|
||||||
std::unique_ptr<Sorter> currentSorter_;
|
std::unique_ptr<Sorter> currentSorter_;
|
||||||
UI ui_;
|
UI ui_;
|
||||||
|
OperationsHistory opsHistory_;
|
||||||
bool isPlaying_;
|
bool isPlaying_;
|
||||||
float timeSinceLastStep_;
|
float timeSinceLastStep_;
|
||||||
int stepsPerFrame_;
|
int stepsPerFrame_;
|
||||||
@@ -37,4 +40,7 @@ private:
|
|||||||
|
|
||||||
size_t lastComparisons_;
|
size_t lastComparisons_;
|
||||||
size_t lastSwaps_;
|
size_t lastSwaps_;
|
||||||
|
|
||||||
|
sf::Font histogramFont_;
|
||||||
|
bool histogramFontLoaded_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <deque>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
class OperationsHistory {
|
||||||
|
public:
|
||||||
|
OperationsHistory(size_t maxSamples = 300);
|
||||||
|
|
||||||
|
void record(size_t comparisons);
|
||||||
|
void reset();
|
||||||
|
const std::deque<size_t>& getHistory() const;
|
||||||
|
size_t getMaxValue() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::deque<size_t> compareHistory_;
|
||||||
|
size_t maxSamples_;
|
||||||
|
};
|
||||||
+78
-8
@@ -6,10 +6,11 @@
|
|||||||
#include "sorters/QuickSorter.hpp"
|
#include "sorters/QuickSorter.hpp"
|
||||||
|
|
||||||
App::App()
|
App::App()
|
||||||
: window_(sf::VideoMode(1280, 720), "SortLab")
|
: window_(sf::VideoMode(1600, 900), "SortLab")
|
||||||
, array_(100)
|
, array_(100)
|
||||||
, currentSorter_(std::make_unique<BubbleSorter>())
|
, currentSorter_(std::make_unique<BubbleSorter>())
|
||||||
, ui_()
|
, ui_()
|
||||||
|
, opsHistory_(300)
|
||||||
, isPlaying_(false)
|
, isPlaying_(false)
|
||||||
, timeSinceLastStep_(0.0f)
|
, timeSinceLastStep_(0.0f)
|
||||||
, stepsPerFrame_(1)
|
, stepsPerFrame_(1)
|
||||||
@@ -18,11 +19,16 @@ App::App()
|
|||||||
, sweepTimer_(0.0f)
|
, sweepTimer_(0.0f)
|
||||||
, sweepDelay_(0.005f)
|
, sweepDelay_(0.005f)
|
||||||
, lastComparisons_(0)
|
, lastComparisons_(0)
|
||||||
, lastSwaps_(0) {
|
, lastSwaps_(0)
|
||||||
|
, histogramFontLoaded_(false) {
|
||||||
window_.setFramerateLimit(60);
|
window_.setFramerateLimit(60);
|
||||||
generateBeepSound();
|
generateBeepSound();
|
||||||
beepSound_.setBuffer(beepBuffer_);
|
beepSound_.setBuffer(beepBuffer_);
|
||||||
beepSound_.setVolume(100.0f);
|
beepSound_.setVolume(100.0f);
|
||||||
|
|
||||||
|
if (histogramFont_.loadFromFile("assets/fonts/JetBrainsMono-Regular.ttf")) {
|
||||||
|
histogramFontLoaded_ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::run() {
|
void App::run() {
|
||||||
@@ -89,6 +95,7 @@ void App::handleEvents() {
|
|||||||
array_.resetStates();
|
array_.resetStates();
|
||||||
array_.resetCounters();
|
array_.resetCounters();
|
||||||
currentSorter_->reset();
|
currentSorter_->reset();
|
||||||
|
opsHistory_.reset();
|
||||||
isPlaying_ = false;
|
isPlaying_ = false;
|
||||||
timeSinceLastStep_ = 0.0f;
|
timeSinceLastStep_ = 0.0f;
|
||||||
isSweeping_ = false;
|
isSweeping_ = false;
|
||||||
@@ -98,6 +105,10 @@ void App::handleEvents() {
|
|||||||
stepsPerFrame_ = 1;
|
stepsPerFrame_ = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case sf::Keyboard::Q:
|
||||||
|
window_.close();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -138,6 +149,7 @@ void App::update(float dt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentSorter_->step(array_);
|
currentSorter_->step(array_);
|
||||||
|
opsHistory_.record(array_.getComparisons());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t afterComparisons = array_.getComparisons();
|
size_t afterComparisons = array_.getComparisons();
|
||||||
@@ -170,15 +182,18 @@ void App::update(float dt) {
|
|||||||
void App::render() {
|
void App::render() {
|
||||||
window_.clear(sf::Color(10, 12, 20));
|
window_.clear(sf::Color(10, 12, 20));
|
||||||
|
|
||||||
|
const float histogramHeight = 120.0f;
|
||||||
|
const float availableHeight = window_.getSize().y - histogramHeight;
|
||||||
|
|
||||||
float width = window_.getSize().x / static_cast<float>(array_.getSize());
|
float width = window_.getSize().x / static_cast<float>(array_.getSize());
|
||||||
float maxVal = static_cast<float>(array_.getSize());
|
float maxVal = static_cast<float>(array_.getSize());
|
||||||
|
|
||||||
sf::VertexArray vertices(sf::Quads);
|
sf::VertexArray vertices(sf::Quads);
|
||||||
|
|
||||||
for (int i = 0; i < array_.getSize(); ++i) {
|
for (int i = 0; i < array_.getSize(); ++i) {
|
||||||
float height = (array_.getValue(i) / maxVal) * (window_.getSize().y * 0.8f);
|
float height = (array_.getValue(i) / maxVal) * (availableHeight * 0.75f);
|
||||||
float x = i * width;
|
float x = i * width;
|
||||||
float y = window_.getSize().y - height;
|
float y = availableHeight - height;
|
||||||
|
|
||||||
sf::Color barColor;
|
sf::Color barColor;
|
||||||
bool useGradient = false;
|
bool useGradient = false;
|
||||||
@@ -215,29 +230,84 @@ void App::render() {
|
|||||||
static_cast<sf::Uint8>(bottomColor.b + (topColor.b - bottomColor.b) * normalizedValue * 0.6f)
|
static_cast<sf::Uint8>(bottomColor.b + (topColor.b - bottomColor.b) * normalizedValue * 0.6f)
|
||||||
);
|
);
|
||||||
|
|
||||||
vertices.append(sf::Vertex(sf::Vector2f(x, window_.getSize().y), gradientBottom));
|
vertices.append(sf::Vertex(sf::Vector2f(x, availableHeight), gradientBottom));
|
||||||
vertices.append(sf::Vertex(sf::Vector2f(x + width - 1.0f, window_.getSize().y), gradientBottom));
|
vertices.append(sf::Vertex(sf::Vector2f(x + width - 1.0f, availableHeight), gradientBottom));
|
||||||
vertices.append(sf::Vertex(sf::Vector2f(x + width - 1.0f, y), gradientTop));
|
vertices.append(sf::Vertex(sf::Vector2f(x + width - 1.0f, y), gradientTop));
|
||||||
vertices.append(sf::Vertex(sf::Vector2f(x, y), gradientTop));
|
vertices.append(sf::Vertex(sf::Vector2f(x, y), gradientTop));
|
||||||
} else {
|
} else {
|
||||||
vertices.append(sf::Vertex(sf::Vector2f(x, window_.getSize().y), barColor));
|
vertices.append(sf::Vertex(sf::Vector2f(x, availableHeight), barColor));
|
||||||
vertices.append(sf::Vertex(sf::Vector2f(x + width - 1.0f, window_.getSize().y), barColor));
|
vertices.append(sf::Vertex(sf::Vector2f(x + width - 1.0f, availableHeight), barColor));
|
||||||
vertices.append(sf::Vertex(sf::Vector2f(x + width - 1.0f, y), barColor));
|
vertices.append(sf::Vertex(sf::Vector2f(x + width - 1.0f, y), barColor));
|
||||||
vertices.append(sf::Vertex(sf::Vector2f(x, y), barColor));
|
vertices.append(sf::Vertex(sf::Vector2f(x, y), barColor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window_.draw(vertices);
|
window_.draw(vertices);
|
||||||
|
renderHistogram();
|
||||||
ui_.draw(window_);
|
ui_.draw(window_);
|
||||||
|
|
||||||
window_.display();
|
window_.display();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void App::renderHistogram() {
|
||||||
|
const float histogramHeight = 120.0f;
|
||||||
|
const float histogramY = window_.getSize().y - histogramHeight;
|
||||||
|
|
||||||
|
sf::RectangleShape background(sf::Vector2f(window_.getSize().x, histogramHeight));
|
||||||
|
background.setPosition(0.0f, histogramY);
|
||||||
|
background.setFillColor(sf::Color(15, 18, 30));
|
||||||
|
window_.draw(background);
|
||||||
|
|
||||||
|
const auto& history = opsHistory_.getHistory();
|
||||||
|
|
||||||
|
if (!history.empty()) {
|
||||||
|
size_t maxValue = opsHistory_.getMaxValue();
|
||||||
|
if (maxValue == 0) maxValue = 1;
|
||||||
|
|
||||||
|
float barWidth = window_.getSize().x / 300.0f;
|
||||||
|
sf::VertexArray histogramBars(sf::Quads);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < history.size(); ++i) {
|
||||||
|
float barHeight = (static_cast<float>(history[i]) / static_cast<float>(maxValue)) * (histogramHeight - 30.0f);
|
||||||
|
float x = i * barWidth;
|
||||||
|
float y = histogramY + histogramHeight - barHeight - 5.0f;
|
||||||
|
|
||||||
|
float normalizedValue = static_cast<float>(history[i]) / static_cast<float>(maxValue);
|
||||||
|
sf::Color lowColor(0, 120, 255);
|
||||||
|
sf::Color highColor(0, 220, 255);
|
||||||
|
|
||||||
|
sf::Color barColor(
|
||||||
|
static_cast<sf::Uint8>(lowColor.r + (highColor.r - lowColor.r) * normalizedValue),
|
||||||
|
static_cast<sf::Uint8>(lowColor.g + (highColor.g - lowColor.g) * normalizedValue),
|
||||||
|
static_cast<sf::Uint8>(lowColor.b + (highColor.b - lowColor.b) * normalizedValue)
|
||||||
|
);
|
||||||
|
|
||||||
|
histogramBars.append(sf::Vertex(sf::Vector2f(x, histogramY + histogramHeight - 5.0f), barColor));
|
||||||
|
histogramBars.append(sf::Vertex(sf::Vector2f(x + barWidth, histogramY + histogramHeight - 5.0f), barColor));
|
||||||
|
histogramBars.append(sf::Vertex(sf::Vector2f(x + barWidth, y), barColor));
|
||||||
|
histogramBars.append(sf::Vertex(sf::Vector2f(x, y), barColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
window_.draw(histogramBars);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (histogramFontLoaded_) {
|
||||||
|
sf::Text label;
|
||||||
|
label.setFont(histogramFont_);
|
||||||
|
label.setString("Comparisons over time");
|
||||||
|
label.setCharacterSize(14);
|
||||||
|
label.setFillColor(sf::Color(180, 180, 180));
|
||||||
|
label.setPosition(10.0f, histogramY + 5.0f);
|
||||||
|
window_.draw(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void App::switchSorter(std::unique_ptr<Sorter> newSorter) {
|
void App::switchSorter(std::unique_ptr<Sorter> newSorter) {
|
||||||
currentSorter_ = std::move(newSorter);
|
currentSorter_ = std::move(newSorter);
|
||||||
array_.shuffle();
|
array_.shuffle();
|
||||||
array_.resetStates();
|
array_.resetStates();
|
||||||
array_.resetCounters();
|
array_.resetCounters();
|
||||||
|
opsHistory_.reset();
|
||||||
isPlaying_ = false;
|
isPlaying_ = false;
|
||||||
timeSinceLastStep_ = 0.0f;
|
timeSinceLastStep_ = 0.0f;
|
||||||
isSweeping_ = false;
|
isSweeping_ = false;
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#include "OperationsHistory.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
OperationsHistory::OperationsHistory(size_t maxSamples)
|
||||||
|
: maxSamples_(maxSamples) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void OperationsHistory::record(size_t comparisons) {
|
||||||
|
compareHistory_.push_back(comparisons);
|
||||||
|
|
||||||
|
if (compareHistory_.size() > maxSamples_) {
|
||||||
|
compareHistory_.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OperationsHistory::reset() {
|
||||||
|
compareHistory_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::deque<size_t>& OperationsHistory::getHistory() const {
|
||||||
|
return compareHistory_;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t OperationsHistory::getMaxValue() const {
|
||||||
|
if (compareHistory_.empty()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *std::max_element(compareHistory_.begin(), compareHistory_.end());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user