Compare commits

..

13 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
lyrgb 005d4282a9 cmake now also includes other dirs in src 2026-08-12 02:05:20 +02:00
lyrgb 8a60e45cd1 timermanager now creates its own timers 2026-08-12 01:43:50 +02:00
lyrgb e6e170a42a split data into sortsession struct with vectors 2026-08-08 14:10:48 +02:00
lyrgb d2d9ef6c70 headers, split steppable 2026-08-07 00:56:06 +02:00
12 changed files with 317 additions and 210 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ project(cppout LANGUAGES CXX)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
file(GLOB SOURCE_FILES "src/*.cpp")
file(GLOB SOURCE_FILES "src/*.cpp" "src/*/*.cpp")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+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
+26 -16
View File
@@ -1,29 +1,39 @@
#include <cstdio>
#include <utility>
#include "sorters.hpp"
#include <cstdio>
#include <iostream>
#include <memory>
#include <utility>
using namespace std;
SteppedBsort::SteppedBsort(shared_ptr<SortInput> input) : data(input) {};
SteppedBsort::SteppedBsort(SortInput &input): data(input) {};
bool SteppedBsort:: step(){
if(is_finished==true) {
void SteppedBsort::step() {
cout << "step in SteppedBsort\n";
if (is_finished) {
printf("finished");
return true;
}
if(data.values[j]>data.values[j+1])
{
swap(data.values[j], data.values[j+1]);
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;
if (j >= data->values.size() - 1 - i) {
j = 0;
i++;
}
if (i==data.values.size()-1){
is_finished=true;
if (i == data->values.size() - 1) {
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;
}
+30 -19
View File
@@ -1,42 +1,53 @@
#ifndef _SORTERS_
#define _SORTERS_
#ifndef SORTERS_HPP
#define SORTERS_HPP
#include <cstddef>
#include <memory>
#include <string>
#include <vector>
#include "timer.hpp"
using namespace std;
#include "Invoker.hpp"
#include "steppable.hpp"
// ground truth domain data
struct SortInput {
string name;
vector<int> values;
std::string name;
std::vector<int> values;
SortInput(string name, vector<int> data)
: name(name), values(data) {}
SortInput(std::string name, std::vector<int> data) : name(name), values(data) {}
};
// ro rendering of data
struct SortView {
shared_ptr<const SortInput> values;
std::shared_ptr<const SortInput> values;
size_t currenttarget = 0;
int x,y;
int x, y;
int color;
SortView(shared_ptr<const SortInput> in): values(in) {}
SortView(std::shared_ptr<const SortInput> in) : values(in) {}
};
class SteppedBsort: Steppable {
public:
SortInput &data;
int stepcount = 0;
// 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;
bool is_finished = false;
SteppedBsort(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
+34 -97
View File
@@ -1,113 +1,50 @@
// for now juist CLI, print an arr, then print each it
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <SFML/Graphics.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Window/Window.hpp>
#include <chrono>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <memory>
#include <sstream>
#include <string>
#include <thread>
#include <utility>
#include <vector>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window/Window.hpp>
#include "timer.hpp"
#include "core/app.hpp"
#include "sessions.hpp"
#include "sorters.hpp"
#include "steppable.hpp"
#include "timer.hpp"
using namespace std::chrono;
using namespace std;
bool displaynumbers(vector<int> input) {
for (size_t i = 0; i < input.size(); ++i) {
printf("array:%d ", input[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, SteppedBsort &mysession){
unique_ptr<Timer> mytimer = make_unique<Timer>(
"sort1", 0,
[&mysession](){return mysession.step();},
milliseconds(250));
mytimermanager.add_timer(std::move(mytimer));
}
struct App{
sf::RenderWindow mywindow;
sf::Font myfont;
sf::Text text;
TimerManager mytimermanager;
SortInput input;
SteppedBsort mystb;
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(SortInput input):
mywindow(sf::VideoMode({800,600}), "mywindow"),
myfont(load_font("assets/NS-R.ttf")),
text(myfont),
input(std::move(input)),
mystb(this->input)
{
text.setFont(myfont);
text.setString("Hello world");
text.setCharacterSize(24);
text.setFillColor(sf::Color::Red);
setupsorttimers(mytimermanager, mystb);
}
void run(){
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(input));
mytimermanager.update_timers();
displaynumbers(input.values);
mywindow.display();
this_thread::sleep_for(milliseconds(250));
}
}
};
vector<int> dataprovider() { return vector<int>{9, 8, 1, 2, 7, 3, 6, 4, 5}; }
int main() {
SortInput myinput("arr1", dataprovider());
App myapp(myinput);
// create data
auto myinput = make_shared<SortInput>("arr1", dataprovider());
auto myinput2 = make_shared<SortInput>("arr2", dataprovider());
auto myviewsession = make_unique<ViewSession>();
auto mytimermanager = make_unique<TimerManager>();
// create app with initialized dependencies
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();
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef STEPPABLE_HPP
#define STEPPABLE_HPP
#include <cstddef>
class Steppable {
public:
virtual ~Steppable() = default;
bool is_finished = 0;
size_t stepcount = 0;
virtual void step() = 0;
};
#endif
+18 -20
View File
@@ -1,40 +1,38 @@
#include <chrono>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include "Invoker.hpp"
#include "timer.hpp"
using namespace std::chrono;
using namespace std;
Timer::Timer(string name, int triggercount, function<bool()> myaction, milliseconds triggerinterval)
: name(name), triggeramount(triggercount), timeraction(myaction), triggerinterval(triggerinterval) {}
Timer::Timer(size_t triggeramount, std::weak_ptr<Invoker> invoker, milliseconds triggerinterval)
: triggeramount(triggeramount), invoker(invoker), triggerinterval(triggerinterval) {}
void Timer::add_time(milliseconds deltatime) {
accumulator += deltatime;
if (accumulator >= triggerinterval) {
accumulator -= triggerinterval;
if (timeraction()==true){
isdone = true;
};
triggercounter++;
if (!isinfinite && triggercounter >= triggeramount){
isexpired=true;
cout << "request in timer\n";
if (auto sp = invoker.lock()) {
sp->request();
}
triggercount++;
if (triggeramount != 0 && triggercount >= triggeramount) {
isexpired = true;
}
}
};
}
void TimerManager::add_timer(unique_ptr<Timer> newtimer) {
timers.push_back(std::move(newtimer));
};
void TimerManager::add_timer(Timer timer) { timers.push_back(std::move(timer)); }
void TimerManager::update_timers() {
steady_clock::time_point currenttime =
steady_clock::now();
milliseconds deltatime = duration_cast<milliseconds>(currenttime-previoustime);
for(unique_ptr<Timer> &mytimer: timers){
mytimer->add_time(deltatime);
steady_clock::time_point currenttime = steady_clock::now();
milliseconds deltatime = duration_cast<milliseconds>(currenttime - previoustime);
for (Timer &mytimer : timers) {
mytimer.add_time(deltatime);
}
previoustime = currenttime;
}
+21 -36
View File
@@ -1,56 +1,41 @@
#ifndef _TIMERS_
#define _TIMERS_
#ifndef TIMER_HPP
#define TIMER_HPP
#include <chrono>
#include <cstddef>
#include <ctime>
#include <functional>
#include <memory>
#include <string>
#include <chrono>
#include <vector>
using namespace std::chrono;
using namespace std;
class Steppable {
public:
bool is_finished = 0;
virtual bool step() = 0;
};
//check if the timer is valid, check if enough time has passed and if so, actuate
#include "Invoker.hpp"
// check if the timer is still valid, check if enough time has passed and if so, actuate action
class Timer {
public:
string name;
public:
size_t triggeramount;
bool isexpired = false;
bool isdone = false;
bool isinfinite = false;
size_t triggercounter = 0;
function<bool()> timeraction;
size_t triggercount = 0;
std::weak_ptr<Invoker> invoker; // if no longer exists, then should clean up timer
Timer(string name, int triggercount, function<bool()> myaction, milliseconds triggerinterval);
void add_time(milliseconds deltatime);
Timer(size_t triggeramount, std::weak_ptr<Invoker> invoker, std::chrono::milliseconds triggerinterval);
void add_time(std::chrono::milliseconds deltatime);
private:
milliseconds accumulator = milliseconds(0);
milliseconds triggerinterval = 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
// CRUD timers and give them dt on update
class TimerManager {
public:
vector<unique_ptr<Timer>> timers;
TimerManager() { previoustime = steady_clock::now(); }
void add_timer(unique_ptr<Timer> newtimer);
public:
std::vector<Timer> timers;
TimerManager() { previoustime = std::chrono::steady_clock::now(); }
// void add_timer(size_t triggeramount, std::function<bool()> myaction, std::chrono::milliseconds triggerinterval);
void add_timer(Timer timer);
void delete_timer();
void update_timers();
private:
steady_clock::time_point previoustime;
private:
std::chrono::steady_clock::time_point previoustime;
};
#endif