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
+24 -15
View File
@@ -1,12 +1,16 @@
#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) { for (size_t i = 0; i < input->values.size(); ++i) {
printf("%d | ", input->values[i]); printf("%d | ", input->values[i]);
} }
@@ -23,32 +27,37 @@ string arraytostr(shared_ptr<SortInput> input) {
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) { for (shared_ptr<SortInput> input : inputs) {
displaySortInput(input); displaySortInput(input);
} }
viewsession->mywindow.display();
myviewsession->mywindow.display(); // update logic
timermanager->update_timers();
this_thread::sleep_for(std::chrono::milliseconds(250)); this_thread::sleep_for(std::chrono::milliseconds(250));
} }
} }
+9 -6
View File
@@ -1,24 +1,27 @@
#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 add_sort(std::shared_ptr<SortInput> myinput, SortBinding mysortbinding);
void run(); void run();
}; };
+2 -2
View File
@@ -2,8 +2,8 @@
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);
-24
View File
@@ -7,32 +7,8 @@
#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
//steppables/sorts are currently updated by timermanager(should be decoupled)
struct SortSession {
vector<unique_ptr<Steppable>> sortsessions;
TimerManager SortTimer;
SortSession(){
}
//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 // sfml/render
struct ViewSession { struct ViewSession {
+18 -9
View File
@@ -1,19 +1,18 @@
#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) {};
bool SteppedBsort:: step(){ void SteppedBsort::step() {
if(is_finished==true) { cout << "step in SteppedBsort\n";
if (is_finished) {
printf("finished"); printf("finished");
return true;
} }
if(data->values[j]>data->values[j+1]) if (data->values[j] > data->values[j + 1]) {
{
swap(data->values[j], data->values[j + 1]); swap(data->values[j], data->values[j + 1]);
} }
j++; j++;
@@ -25,6 +24,16 @@ bool SteppedBsort:: step(){
if (i == data->values.size() - 1) { if (i == data->values.size() - 1) {
is_finished = true; is_finished = true;
} }
}
return false;
SortBinding::SortBinding(
std::shared_ptr<SortInput> input, std::shared_ptr<Steppable> sort, std::shared_ptr<Invoker> invoker)
: input(std::move(input)), sort(std::move(sort)), invoker(std::move(invoker)) {}
// connects data with the correct sort
std::shared_ptr<Steppable> make_sort(std::shared_ptr<SortInput> input, std::string sorttype) {
if (sorttype == "bsort") {
return make_shared<SteppedBsort>(input);
}
return nullptr;
} }
+19 -11
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
+21 -15
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);
inputs.push_back(myinput2);
//connect data with sorter
auto myssession = make_unique<SortSession>();
myssession->add_session(myinput, "bsort");
auto myviewsession = make_unique<ViewSession>(); auto myviewsession = make_unique<ViewSession>();
auto mytimermanager = make_unique<TimerManager>();
// create app with initialized dependencies // create app with initialized dependencies
App myapp(std::move(inputs), std::move(myssession), std::move(myviewsession)); 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(); myapp.run();
} }
+1 -1
View File
@@ -8,7 +8,7 @@ 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
+13 -15
View File
@@ -1,37 +1,35 @@
#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";
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(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);
+7 -8
View File
@@ -1,23 +1,22 @@
#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>
#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; bool isexpired = false;
bool isinfinite = false;
size_t triggercount = 0; size_t triggercount = 0;
std::function<bool()> timeraction; std::weak_ptr<Invoker> invoker; // if no longer exists, then should clean up timer
Timer(size_t triggeramount, std::function<bool()> myaction, std::chrono::milliseconds triggerinterval); Timer(size_t triggeramount, std::weak_ptr<Invoker> invoker, std::chrono::milliseconds triggerinterval);
void add_time(std::chrono::milliseconds deltatime); void add_time(std::chrono::milliseconds deltatime);
private: private:
@@ -25,13 +24,13 @@ private:
std::chrono::milliseconds triggerinterval = std::chrono::milliseconds(1000); // default to 1 sec 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 add_timer(Timer timer);
void delete_timer(); void delete_timer();
void update_timers(); void update_timers();