Compare commits

...

9 Commits

Author SHA1 Message Date
lyrgb a8894a51cd clang formatting 2026-08-30 01:40:29 +02:00
lyrgb c330f13bb8 moved instantiation responsibility from App::add_sort
Invoker is now an object that we attach to the sortbinding rather than
the HasInvoker.
we now create a binding in main, then pass it on to App.
Timer now has a weak ptr to its invoker, so it could clean itself up.
2026-08-28 00:48:53 +02:00
lyrgb d98c29ecbb Timer now contains an invoker instead of inheriting
the idea is that an invoker holds a weak_ptr to a steppable. and
anything with an invoker can advance a steppable

app::add_sort has become too heavy because of the way timer and
invoker are initialized now.
2026-08-24 01:56:04 +02:00
lyrgb 273ff07a00 cleanup, timermanager in App is a dependency that takes timers again.
App now adds already constructed Timers
Timer is now an Invoker that takes a weak_ptr to a steppable with a
request()rather than a bool callback.
should eventually be changed to composition
2026-08-23 23:25:04 +02:00
lyrgb 54faab2a28 added invoker virtual class and made timer inherit from it 2026-08-20 14:44:16 +02:00
lyrgb 2185d2858a App now uses separate add_session to insert data into it
improved the hub and spoke-ish model of App by making it more clear
that its components have specific responsibilities, which App then
glues together.

moved timermanager to App to seperate the invoker from receiver so we
can eventually add interactivity

also fixed the using namespace std error from a while ago
2026-08-20 01:47:38 +02:00
lyrgb b5309278cf rename myaction to callback 2026-08-20 00:45:52 +02:00
lyrgb 6e71aeebb4 app now just coordinates the components initialized in main
reduced responsibilities of constructors
started using more pointers.
sessions through app rather than app itself.
mostly split view away from app (still hard coded)
haven't decoupled sorts from timers as their actuator yet
2026-08-15 03:14:54 +02:00
lyrgb afdf73ca2e split app into seperate files to clean main 2026-08-12 13:04:49 +02:00
11 changed files with 292 additions and 225 deletions
+18
View File
@@ -0,0 +1,18 @@
#ifndef INVOKER_HPP
#define INVOKER_HPP
#include "steppable.hpp"
#include <memory>
class Invoker {
public:
std::weak_ptr<Steppable> target;
Invoker(std::shared_ptr<Steppable> t) { target = t; }
void request() {
if (auto sp = target.lock()) {
sp->step();
}
}
};
#endif
+63
View File
@@ -0,0 +1,63 @@
#include <SFML/Graphics/Font.hpp>
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>
#include "./app.hpp"
using namespace std;
bool displaySortInput(shared_ptr<SortInput> input) {
cout << "name: " + input->name + " values: ";
for (size_t i = 0; i < input->values.size(); ++i) {
printf("%d | ", input->values[i]);
}
printf("\n");
return false;
}
string arraytostr(shared_ptr<SortInput> input) {
string myoutput;
ostringstream stringrep;
for (size_t i = 0; i < input->values.size(); ++i) {
stringrep << input->values[i] << " | ";
}
return stringrep.str();
}
App::App(unique_ptr<ViewSession> myviewsession, unique_ptr<TimerManager> mytimermanager)
: viewsession(std::move(myviewsession)), timermanager(std::move(mytimermanager)) {}
// just pushes to App for now
void App::add_sort(shared_ptr<SortInput> myinput, SortBinding mysortbinding) {
cout << "adding sort " << myinput->name << "\n";
// insert data
inputs.push_back(myinput);
// move the sort into app
sortbindings.push_back(mysortbinding);
}
void App::run() {
// set up ui
while (viewsession->mywindow.isOpen()) {
while (const optional event = viewsession->mywindow.pollEvent()) {
if (event->is<sf::Event::Closed>()) viewsession->mywindow.close();
}
// draw
viewsession->mywindow.clear(sf::Color::Black);
viewsession->mywindow.draw(viewsession->text);
viewsession->text.setString(arraytostr(inputs[0]));
for (shared_ptr<SortInput> input : inputs) {
displaySortInput(input);
}
viewsession->mywindow.display();
// update logic
timermanager->update_timers();
this_thread::sleep_for(std::chrono::milliseconds(250));
}
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef APP_HPP
#define APP_HPP
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/Text.hpp>
#include <memory>
#include <vector>
#include "../sessions.hpp"
#include "../sorters.hpp"
#include "../timer.hpp"
// should connect the different parts
// for now data, mutation, and rendering
struct App {
std::vector<std::shared_ptr<SortInput>> inputs;
std::vector<SortBinding> sortbindings;
std::unique_ptr<ViewSession> viewsession;
std::unique_ptr<TimerManager> timermanager;
App(std::unique_ptr<ViewSession> myviewsession, std::unique_ptr<TimerManager> mytimermanager);
void add_sort(std::shared_ptr<SortInput> myinput, SortBinding mysortbinding);
void run();
};
#endif
+20
View File
@@ -0,0 +1,20 @@
#include "sessions.hpp"
using namespace std;
ViewSession::ViewSession()
: mywindow(sf::VideoMode({800, 600}), "mywindow"), myfont(load_font("assets/NS-R.ttf")), text(myfont) {
text.setFont(myfont);
text.setString("Hello world");
text.setCharacterSize(24);
text.setFillColor(sf::Color::Red);
};
sf::Font ViewSession::load_font(const std::string &filename) {
sf::Font font;
if (!font.openFromFile(filename)) {
fprintf(stderr, "failed to load font");
std::exit(1);
}
return font;
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef SESSIONS_HPP
#define SESSIONS_HPP
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/Text.hpp>
#include <vector>
#include "sorters.hpp"
// owns and manages the sorters that mutate data, but does not own the data itself
// sfml/render
struct ViewSession {
sf::RenderWindow mywindow;
sf::Font myfont;
sf::Text text;
ViewSession();
sf::Font load_font(const std::string &filename);
};
#endif
+33 -23
View File
@@ -1,29 +1,39 @@
#include <cstdio>
#include <utility>
#include "sorters.hpp" #include "sorters.hpp"
#include <cstdio>
#include <iostream>
#include <memory>
#include <utility>
using namespace std; using namespace std;
SteppedBsort::SteppedBsort(shared_ptr<SortInput> input) : data(input) {};
SteppedBsort::SteppedBsort(SortInput &input): data(input) {}; void SteppedBsort::step() {
cout << "step in SteppedBsort\n";
if (is_finished) {
printf("finished");
}
if (data->values[j] > data->values[j + 1]) {
swap(data->values[j], data->values[j + 1]);
}
j++;
if (j >= data->values.size() - 1 - i) {
j = 0;
i++;
}
bool SteppedBsort:: step(){ if (i == data->values.size() - 1) {
if(is_finished==true) { is_finished = true;
printf("finished"); }
return true; }
}
if(data.values[j]>data.values[j+1]) SortBinding::SortBinding(
{ std::shared_ptr<SortInput> input, std::shared_ptr<Steppable> sort, std::shared_ptr<Invoker> invoker)
swap(data.values[j], data.values[j+1]); : input(std::move(input)), sort(std::move(sort)), invoker(std::move(invoker)) {}
}
j++; // connects data with the correct sort
if(j>=data.values.size()-1 -i){ std::shared_ptr<Steppable> make_sort(std::shared_ptr<SortInput> input, std::string sorttype) {
j=0; if (sorttype == "bsort") {
i++; return make_shared<SteppedBsort>(input);
} }
return nullptr;
if (i==data.values.size()-1){
is_finished=true;
}
return false;
} }
+33 -23
View File
@@ -6,38 +6,48 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "Invoker.hpp"
#include "steppable.hpp" #include "steppable.hpp"
using namespace std; // ground truth domain data
struct SortInput { struct SortInput {
string name; std::string name;
vector<int> values; std::vector<int> values;
SortInput(string name, vector<int> data) SortInput(std::string name, std::vector<int> data) : name(name), values(data) {}
: name(name), values(data) {}
}; };
// ro rendering of data
struct SortView { struct SortView {
shared_ptr<const SortInput> values; std::shared_ptr<const SortInput> values;
size_t currenttarget = 0; size_t currenttarget = 0;
int x,y; int x, y;
int color; int color;
SortView(shared_ptr<const SortInput> in): values(in) {} SortView(std::shared_ptr<const SortInput> in) : values(in) {}
}; };
// mutates the domain data
class SteppedBsort : public Steppable {
public:
std::shared_ptr<SortInput> data;
size_t stepcount = 0;
size_t i = 0;
size_t j = 0;
bool is_finished = false;
class SteppedBsort: public Steppable { SteppedBsort(std::shared_ptr<SortInput> data);
public:
SortInput &data; void step();
size_t stepcount = 0;
size_t i = 0;
size_t j = 0;
bool is_finished = false;
SteppedBsort(SortInput &data);
bool step();
}; };
#endif // working unit
struct SortBinding {
std::shared_ptr<SortInput> input;
std::shared_ptr<Steppable> sort;
std::shared_ptr<Invoker> invoker;
SortBinding(std::shared_ptr<SortInput> input, std::shared_ptr<Steppable> sort, std::shared_ptr<Invoker> invoker);
};
std::shared_ptr<Steppable> make_sort(std::shared_ptr<SortInput> input, std::string sorttype);
#endif
+27 -126
View File
@@ -1,149 +1,50 @@
// for now juist CLI, print an arr, then print each it // for now juist CLI, print an arr, then print each it
#include <chrono>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <memory> #include <memory>
#include <sstream>
#include <string> #include <string>
#include <thread>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <SFML/Graphics.hpp>
#include <SFML/Graphics/Color.hpp> #include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Font.hpp> #include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/RenderWindow.hpp> #include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/Text.hpp> #include <SFML/Graphics/Text.hpp>
#include <SFML/Window/Window.hpp>
#include <SFML/Window.hpp> #include <SFML/Window.hpp>
#include <SFML/Graphics.hpp> #include <SFML/Window/Window.hpp>
#include "core/app.hpp"
#include "sessions.hpp"
#include "sorters.hpp"
#include "steppable.hpp" #include "steppable.hpp"
#include "timer.hpp" #include "timer.hpp"
#include "sorters.hpp"
using namespace std::chrono; using namespace std::chrono;
using namespace std; using namespace std;
bool displaySortInput(SortInput input) { vector<int> dataprovider() { return vector<int>{9, 8, 1, 2, 7, 3, 6, 4, 5}; }
cout << "name: " + input.name + " values: ";
for (size_t i = 0; i < input.values.size(); ++i) {
printf("%d | ",input.values[i]);
}
printf("\n");
return false;
}
string arraytostr(SortInput input) {
string myoutput;
ostringstream stringrep;
for (size_t i = 0; i < input.values.size(); ++i) {
stringrep << input.values[i] <<" | ";
}
return stringrep.str();
}
vector<int> dataprovider(){
return vector<int> {9,8,1,2,7,3,6,4,5};
}
void setupsorttimers(TimerManager &mytimermanager, unique_ptr<Steppable> &mysession){
mytimermanager.add_timer(
0,
[&mysession](){return mysession->step();},
milliseconds(250));
}
//list of inputs, manually assign them to sorts
struct SortSession {
vector<SortInput> &inputs;
unique_ptr<Steppable> sorts;
TimerManager SortTimer;
SortSession(vector<SortInput> &inputs): inputs(inputs), sorts(make_unique<SteppedBsort>(inputs[0])) {
//setupsorttimers(SortTimer, sorts);
add_session(sorts);
}
void add_session(unique_ptr<Steppable> &mysteppable){
SortTimer.add_timer(0,
[&mysteppable]() {return mysteppable->step();},
milliseconds(250));
}
void update_sorts(){
SortTimer.update_timers();
}
};
struct ViewSession{
sf::RenderWindow mywindow;
sf::Font myfont;
sf::Text text;
};
struct App{
sf::RenderWindow mywindow;
sf::Font myfont;
sf::Text text;
vector<SortInput> inputs;
SortSession mysortsession;
sf::Font load_font(const string &filename) {
sf::Font font;
if (!font.openFromFile(filename)){
fprintf(stderr, "failed to load font");
std::exit(1);
}
return font;
}
App(vector<SortInput> inputs):
mywindow(sf::VideoMode({800,600}), "mywindow"),
myfont(load_font("assets/NS-R.ttf")),
text(myfont),
inputs(std::move(inputs)),
mysortsession(this->inputs)
{
text.setFont(myfont);
text.setString("Hello world");
text.setCharacterSize(24);
text.setFillColor(sf::Color::Red);
}
void run(){
//set up ui
while (mywindow.isOpen()){
while (const optional event = mywindow.pollEvent()){
if (event->is<sf::Event::Closed>())
mywindow.close();
}
mywindow.clear(sf::Color::Black);
mywindow.draw(text);
text.setString(arraytostr(inputs[0]));
mysortsession.update_sorts();
for (SortInput input : inputs) {
displaySortInput(input);
}
mywindow.display();
this_thread::sleep_for(milliseconds(250));
}
}
};
int main() { int main() {
vector<SortInput> inputs; // create data
SortInput myinput("arr1", dataprovider()); auto myinput = make_shared<SortInput>("arr1", dataprovider());
SortInput myinput2("arr2", dataprovider()); auto myinput2 = make_shared<SortInput>("arr2", dataprovider());
inputs.push_back(myinput); auto myviewsession = make_unique<ViewSession>();
inputs.push_back(myinput2); auto mytimermanager = make_unique<TimerManager>();
App myapp(inputs); // create app with initialized dependencies
myapp.run(); App myapp(std::move(myviewsession), std::move(mytimermanager));
// create binding
shared_ptr<Steppable> asort = make_sort(myinput, "bsort");
shared_ptr<Invoker> myinvoker = make_shared<Invoker>(asort);
SortBinding mysortbinding(myinput, asort, myinvoker);
Timer timer(0, myinvoker, chrono::milliseconds(250));
myapp.timermanager->add_timer(std::move(timer));
// add data and binding
myapp.add_sort(myinput, mysortbinding);
// actually start the app
myapp.run();
} }
+5 -5
View File
@@ -4,11 +4,11 @@
#include <cstddef> #include <cstddef>
class Steppable { class Steppable {
public: public:
virtual ~Steppable() = default; virtual ~Steppable() = default;
bool is_finished = 0; bool is_finished = 0;
size_t stepcount = 0; size_t stepcount = 0;
virtual bool step() = 0; virtual void step() = 0;
}; };
#endif #endif
+19 -20
View File
@@ -1,39 +1,38 @@
#include <chrono> #include <chrono>
#include <functional> #include <iostream>
#include <memory> #include <memory>
#include <string>
#include <utility> #include "Invoker.hpp"
#include "timer.hpp" #include "timer.hpp"
using namespace std::chrono; using namespace std::chrono;
using namespace std; using namespace std;
Timer::Timer(size_t triggeramount, function<bool()> myaction, milliseconds triggerinterval) Timer::Timer(size_t triggeramount, std::weak_ptr<Invoker> invoker, milliseconds triggerinterval)
:triggeramount(triggeramount), timeraction(myaction), triggerinterval(triggerinterval) {} : triggeramount(triggeramount), invoker(invoker), triggerinterval(triggerinterval) {}
void Timer::add_time(milliseconds deltatime) { void Timer::add_time(milliseconds deltatime) {
accumulator += deltatime; accumulator += deltatime;
if (accumulator >= triggerinterval) { if (accumulator >= triggerinterval) {
accumulator -= triggerinterval; accumulator -= triggerinterval;
timeraction(); cout << "request in timer\n";
if (auto sp = invoker.lock()) {
sp->request();
}
triggercount++; triggercount++;
if (!isinfinite && triggercount >= triggeramount){ if (triggeramount != 0 && triggercount >= triggeramount) {
isexpired=true; isexpired = true;
} }
} }
}; }
void TimerManager::add_timer(size_t triggeramount, function<bool()> myaction, std::chrono::milliseconds triggerinterval) { void TimerManager::add_timer(Timer timer) { timers.push_back(std::move(timer)); }
Timer mynewtimer(triggeramount, myaction, triggerinterval);
timers.push_back(mynewtimer);
};
void TimerManager::update_timers() { void TimerManager::update_timers() {
steady_clock::time_point currenttime = steady_clock::time_point currenttime = steady_clock::now();
steady_clock::now(); milliseconds deltatime = duration_cast<milliseconds>(currenttime - previoustime);
milliseconds deltatime = duration_cast<milliseconds>(currenttime-previoustime); for (Timer &mytimer : timers) {
for(Timer &mytimer: timers){ mytimer.add_time(deltatime);
mytimer.add_time(deltatime);
} }
previoustime = currenttime; previoustime = currenttime;
} }
+23 -28
View File
@@ -1,46 +1,41 @@
#ifndef TIMER_HPP #ifndef TIMER_HPP
#define TIMER_HPP #define TIMER_HPP
#include <chrono>
#include <cstddef> #include <cstddef>
#include <ctime> #include <ctime>
#include <functional>
#include <memory> #include <memory>
#include <string>
#include <chrono>
#include <vector> #include <vector>
using namespace std; #include "Invoker.hpp"
//check if the timer is still valid, check if enough time has passed and if so, actuate action // check if the timer is still valid, check if enough time has passed and if so, actuate action
class Timer { class Timer {
public: public:
size_t triggeramount; size_t triggeramount;
bool isexpired = false;
size_t triggercount = 0;
std::weak_ptr<Invoker> invoker; // if no longer exists, then should clean up timer
bool isexpired = false; Timer(size_t triggeramount, std::weak_ptr<Invoker> invoker, std::chrono::milliseconds triggerinterval);
bool isinfinite = false; void add_time(std::chrono::milliseconds deltatime);
size_t triggercount = 0;
function<bool()> timeraction;
Timer(size_t triggeramount, function<bool()> myaction, std::chrono::milliseconds triggerinterval); private:
void add_time(std::chrono::milliseconds deltatime); std::chrono::milliseconds accumulator = std::chrono::milliseconds(0);
std::chrono::milliseconds triggerinterval = std::chrono::milliseconds(1000); // default to 1 sec
private:
std::chrono::milliseconds accumulator = std::chrono::milliseconds(0);
std::chrono::milliseconds triggerinterval = std::chrono::milliseconds(1000); //default to 1 sec
}; };
// CRUD timers and give them dt on update
//CRUD timers and give them dt on update
class TimerManager { class TimerManager {
public: public:
vector<Timer> timers; std::vector<Timer> timers;
TimerManager(){previoustime = std::chrono::steady_clock::now();} TimerManager() { previoustime = std::chrono::steady_clock::now(); }
void add_timer(size_t triggeramount, function<bool()> myaction, std::chrono::milliseconds triggerinterval); // void add_timer(size_t triggeramount, std::function<bool()> myaction, std::chrono::milliseconds triggerinterval);
void delete_timer(); void add_timer(Timer timer);
void update_timers(); void delete_timer();
void update_timers();
private: private:
std::chrono::steady_clock::time_point previoustime; std::chrono::steady_clock::time_point previoustime;
}; };
#endif #endif