Compare commits

...

7 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
11 changed files with 237 additions and 211 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
+44 -35
View File
@@ -1,54 +1,63 @@
#include <SFML/Graphics/Font.hpp> #include <SFML/Graphics/Font.hpp>
#include <chrono>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <thread> #include <thread>
#include "./app.hpp" #include "./app.hpp"
using namespace std;
bool displaySortInput(shared_ptr<SortInput> input) { bool displaySortInput(shared_ptr<SortInput> input) {
cout << "name: " + input->name + " values: "; cout << "name: " + input->name + " values: ";
for (size_t i = 0; i < input->values.size(); ++i) {
printf("%d | ",input->values[i]); for (size_t i = 0; i < input->values.size(); ++i) {
} printf("%d | ", input->values[i]);
printf("\n"); }
return false; printf("\n");
return false;
} }
string arraytostr(shared_ptr<SortInput> input) { string arraytostr(shared_ptr<SortInput> input) {
string myoutput; string myoutput;
ostringstream stringrep; ostringstream stringrep;
for (size_t i = 0; i < input->values.size(); ++i) { for (size_t i = 0; i < input->values.size(); ++i) {
stringrep << input->values[i] <<" | "; stringrep << input->values[i] << " | ";
} }
return stringrep.str(); return stringrep.str();
} }
App::App(vector<shared_ptr<SortInput>> inputs, unique_ptr<SortSession> mysortsession, unique_ptr<ViewSession> myviewsession) App::App(unique_ptr<ViewSession> myviewsession, unique_ptr<TimerManager> mytimermanager)
: inputs(std::move(inputs)) : viewsession(std::move(myviewsession)), timermanager(std::move(mytimermanager)) {}
, mysortsession(std::move(mysortsession))
, myviewsession(std::move(myviewsession)) // 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(){ void App::run() {
//set up ui // set up ui
while (myviewsession->mywindow.isOpen()){ while (viewsession->mywindow.isOpen()) {
while (const optional event = myviewsession->mywindow.pollEvent()){ while (const optional event = viewsession->mywindow.pollEvent()) {
if (event->is<sf::Event::Closed>()) if (event->is<sf::Event::Closed>()) viewsession->mywindow.close();
myviewsession->mywindow.close(); }
}
myviewsession->mywindow.clear(sf::Color::Black); // draw
myviewsession->mywindow.draw(myviewsession->text); viewsession->mywindow.clear(sf::Color::Black);
myviewsession->text.setString(arraytostr(inputs[0])); viewsession->mywindow.draw(viewsession->text);
viewsession->text.setString(arraytostr(inputs[0]));
mysortsession->update_sorts(); for (shared_ptr<SortInput> input : inputs) {
displaySortInput(input);
}
viewsession->mywindow.display();
for (shared_ptr<SortInput> input : inputs) { // update logic
displaySortInput(input); timermanager->update_timers();
} this_thread::sleep_for(std::chrono::milliseconds(250));
}
myviewsession->mywindow.display();
this_thread::sleep_for(std::chrono::milliseconds(250));
}
} }
+13 -10
View File
@@ -1,25 +1,28 @@
#ifndef APP_HPP #ifndef APP_HPP
#define APP_HPP #define APP_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 <memory> #include <memory>
#include <vector>
#include "../sorters.hpp"
#include "../sessions.hpp" #include "../sessions.hpp"
#include "../sorters.hpp"
#include "../timer.hpp"
//should connect the different parts // should connect the different parts
//for now data, mutation, and rendering // for now data, mutation, and rendering
struct App{ struct App {
vector<shared_ptr<SortInput>> inputs; std::vector<std::shared_ptr<SortInput>> inputs;
unique_ptr<SortSession> mysortsession; std::vector<SortBinding> sortbindings;
unique_ptr<ViewSession> myviewsession; std::unique_ptr<ViewSession> viewsession;
std::unique_ptr<TimerManager> timermanager;
App(vector<shared_ptr<SortInput>> inputs, unique_ptr<SortSession> mysortsession, unique_ptr<ViewSession> myviewsession); App(std::unique_ptr<ViewSession> myviewsession, std::unique_ptr<TimerManager> mytimermanager);
void run(); void add_sort(std::shared_ptr<SortInput> myinput, SortBinding mysortbinding);
void run();
}; };
#endif #endif
+13 -13
View File
@@ -2,19 +2,19 @@
using namespace std; using namespace std;
ViewSession::ViewSession(): mywindow(sf::VideoMode({800,600}), "mywindow"), myfont(load_font("assets/NS-R.ttf")), text(myfont) ViewSession::ViewSession()
{ : mywindow(sf::VideoMode({800, 600}), "mywindow"), myfont(load_font("assets/NS-R.ttf")), text(myfont) {
text.setFont(myfont); text.setFont(myfont);
text.setString("Hello world"); text.setString("Hello world");
text.setCharacterSize(24); text.setCharacterSize(24);
text.setFillColor(sf::Color::Red); text.setFillColor(sf::Color::Red);
}; };
sf::Font ViewSession::load_font(const std::string &filename){ sf::Font ViewSession::load_font(const std::string &filename) {
sf::Font font; sf::Font font;
if (!font.openFromFile(filename)){ if (!font.openFromFile(filename)) {
fprintf(stderr, "failed to load font"); fprintf(stderr, "failed to load font");
std::exit(1); std::exit(1);
} }
return font; return font;
} }
+8 -32
View File
@@ -7,41 +7,17 @@
#include <vector> #include <vector>
#include "sorters.hpp" #include "sorters.hpp"
#include "timer.hpp"
// owns and manages the sorters that mutate data, but does not own the data itself
//owns and manages the sorters that mutate data, but does not own the data itself // sfml/render
//steppables/sorts are currently updated by timermanager(should be decoupled) struct ViewSession {
struct SortSession { sf::RenderWindow mywindow;
vector<unique_ptr<Steppable>> sortsessions; sf::Font myfont;
TimerManager SortTimer; sf::Text text;
SortSession(){ ViewSession();
} sf::Font load_font(const std::string &filename);
//connects data with a sorter and controls it through a timer
void add_session(shared_ptr<SortInput> input, string sorttype){
if(sorttype == "bsort"){
sortsessions.push_back(make_unique<SteppedBsort>(input));
}
auto prs = sortsessions.back().get();
SortTimer.add_timer(0,
[prs]() {return prs->step();},
std::chrono::milliseconds(250));
}
void update_sorts(){
SortTimer.update_timers();
}
};
//sfml/render
struct ViewSession{
sf::RenderWindow mywindow;
sf::Font myfont;
sf::Text text;
ViewSession();
sf::Font load_font(const std::string &filename);
}; };
#endif #endif
+31 -22
View File
@@ -1,30 +1,39 @@
#include "sorters.hpp"
#include <cstdio> #include <cstdio>
#include <iostream>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "sorters.hpp"
using namespace std; using namespace std;
SteppedBsort::SteppedBsort(shared_ptr<SortInput> input) : data(input) {};
SteppedBsort::SteppedBsort(shared_ptr<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;
} }
+31 -23
View File
@@ -6,40 +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
//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 // 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 // mutates the domain data
class SteppedBsort: public Steppable { class SteppedBsort : public Steppable {
public: public:
shared_ptr<SortInput> data; std::shared_ptr<SortInput> data;
size_t stepcount = 0; size_t stepcount = 0;
size_t i = 0; size_t i = 0;
size_t j = 0; size_t j = 0;
bool is_finished = false; bool is_finished = false;
SteppedBsort(shared_ptr<SortInput> data); SteppedBsort(std::shared_ptr<SortInput> data);
bool step(); void step();
}; };
// 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 #endif
+25 -19
View File
@@ -1,44 +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 <memory> #include <memory>
#include <string> #include <string>
#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 "core/app.hpp"
#include "sessions.hpp" #include "sessions.hpp"
#include "sorters.hpp" #include "sorters.hpp"
#include "steppable.hpp"
#include "timer.hpp"
using namespace std::chrono; using namespace std::chrono;
using namespace std; using namespace std;
vector<int> dataprovider() { return vector<int>{9, 8, 1, 2, 7, 3, 6, 4, 5}; }
vector<int> dataprovider(){
return vector<int> {9,8,1,2,7,3,6,4,5};
}
int main() { int main() {
//create data // create data
vector<shared_ptr<SortInput>> inputs; auto myinput = make_shared<SortInput>("arr1", dataprovider());
auto myinput = make_shared<SortInput>("arr1", dataprovider()); auto myinput2 = make_shared<SortInput>("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>();
//connect data with sorter // create app with initialized dependencies
auto myssession = make_unique<SortSession>(); App myapp(std::move(myviewsession), std::move(mytimermanager));
myssession->add_session(myinput, "bsort");
auto myviewsession = make_unique<ViewSession>(); // create binding
shared_ptr<Steppable> asort = make_sort(myinput, "bsort");
shared_ptr<Invoker> myinvoker = make_shared<Invoker>(asort);
SortBinding mysortbinding(myinput, asort, myinvoker);
//create app with initialized dependencies Timer timer(0, myinvoker, chrono::milliseconds(250));
App myapp(std::move(inputs), std::move(myssession), std::move(myviewsession)); myapp.timermanager->add_timer(std::move(timer));
myapp.run();
// 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
+25 -27
View File
@@ -1,40 +1,38 @@
#include <chrono> #include <chrono>
#include <functional> #include <iostream>
#include <utility> #include <memory>
#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) : triggeramount(triggeramount), invoker(invoker), triggerinterval(triggerinterval) {}
, timeraction(myaction)
, 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";
triggercount++; if (auto sp = invoker.lock()) {
if (!isinfinite && triggercount >= triggeramount){ sp->request();
isexpired=true; }
} triggercount++;
} if (triggeramount != 0 && triggercount >= triggeramount) {
}; 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(std::move(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;
} }
+24 -25
View File
@@ -1,42 +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 <chrono>
#include <vector> #include <vector>
//check if the timer is still valid, check if enough time has passed and if so, actuate action #include "Invoker.hpp"
// 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;
std::function<bool()> timeraction;
Timer(size_t triggeramount, std::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:
std::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, std::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