Skip to content

Instantly share code, notes, and snippets.

@JamesBremner
Created October 5, 2023 17:35
Show Gist options
  • Save JamesBremner/873e02020b369cb55e8b7915ca3d17cd to your computer and use it in GitHub Desktop.
Save JamesBremner/873e02020b369cb55e8b7915ca3d17cd to your computer and use it in GitHub Desktop.
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <wex.h>
#include "plot2d.h"
#include "cStarterGUI.h"
class cTrains
{
std::vector<std::vector<std::string>> vHourlySchedule;
std::vector<std::vector<int>> vSecsSchedule;
int maxsecs;
public:
cTrains()
{
generateHourlySchedule();
convertScheduleToSecs();
}
void generateHourlySchedule()
{
vHourlySchedule = {
{":35:00", ":38:18", ":45:06"},
{":55:06", ":59:12", ":06:18"},
{":12:00", ":18:12", ":23:18"}};
}
void convertScheduleToSecs()
{
maxsecs = 0;
for (auto &train : vHourlySchedule)
{
std::vector<int> trainSchedule;
for (std::string &minsec : train)
{
if (!trainSchedule.size())
trainSchedule.push_back(fms2secs(0, minsec));
else
{
int secs = fms2secs(trainSchedule[0], minsec);
trainSchedule.push_back(secs);
if (secs > maxsecs)
maxsecs = secs;
}
}
vSecsSchedule.push_back(trainSchedule);
}
}
int trainY(int train, int sec) const
{
if (0 > train || train >= trainCount())
throw std::runtime_error("trainY bad train index");
const int stationYinc = 100;
const int stopsecs = 42;
for (int station = 0; station < vSecsSchedule[train].size() - 1; station++)
{
int prev = 0;
if (station > 0)
prev = vSecsSchedule[train][station - 1];
int arr = vSecsSchedule[train][station];
int nxt = vSecsSchedule[train][station + 1];
int stationY = (station + 1) * stationYinc;
// check if train has not left the station yet
if (sec < arr + stopsecs)
return stationY + train;
// check if train on way to next station
if (sec < nxt)
{
// interpolate between stations
double f = ((float)(sec - arr - stopsecs)) / ((float)(nxt - arr - stopsecs));
return stationY + f * stationYinc + train;
}
}
// train has arrived at last station
return vSecsSchedule[train].size() * stationYinc + train;
}
int trainCount() const
{
return vHourlySchedule.size();
}
std::vector<double> plot(int train)
{
const int secinc = 10;
if (0 > train || train >= trainCount())
throw std::runtime_error("plot bad train index");
std::vector<double> ret;
for (int s = 0; s < maxsecs; s += secinc)
ret.push_back(trainY(train, s));
return ret;
}
private:
int fms2secs(
int secs1, // secs since epoch at station 1, 0 if not yet available
const std::string &minsec) // time at station to be converted
{
int s = 60 * atoi(minsec.substr(1, 2).c_str()) + atoi(minsec.substr(4, 2).c_str());
if (s < secs1) // check for hour wrap
s = s + 60 * 60;
return s;
}
};
class cGUI : public cStarterGUI
{
public:
cGUI()
: cStarterGUI(
"Trains",
{50, 50, 1000, 500}),
thePlot(wex::maker::make<wex::plot::plot>(fm))
{
thePlot.move({30, 30, 1200, 600});
// construct plot traces
wex::plot::trace &t1 = thePlot.AddStaticTrace();
wex::plot::trace &t2 = thePlot.AddStaticTrace();
wex::plot::trace &t3 = thePlot.AddStaticTrace();
t1.color(0x0000FF);
t2.color(0xFF0000);
t3.color(0xAAFFAA);
auto d1 = myTrains.plot(0);
t1.set(d1);
d1 = myTrains.plot(1);
t2.set(d1);
d1 = myTrains.plot(2);
t3.set(d1);
// resize plot when form resizes
fm.events().resize(
[&](int w, int h)
{
thePlot.move({30, 30, w, h});
thePlot.update();
});
show();
run();
}
private:
cTrains myTrains;
wex::plot::plot &thePlot;
};
main()
{
cGUI theGUI;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment