Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions chat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include <netdb.h>
#include <experimental/filesystem>

Chat::Chat(const QuesoQueue &qq, const Timer &timer) : _qq(qq), _timer(timer) {
Chat::Chat(const QuesoQueue &qq, const Twitch &twitch, const Timer &timer) : _qq(qq), _twitch(twitch), _timer(timer) {
namespace fs = std::experimental::filesystem;
static const std::regex chipModuleRegex(".*\\.so", std::regex_constants::egrep);

Expand Down Expand Up @@ -109,6 +109,7 @@ void Chat::Listen() {
// Get message body
std::string messageBody = m[2];

_twitch.markAsOnline(username);
HandleMessage(std::stringstream(messageBody), username);
continue;
}
Expand All @@ -135,8 +136,10 @@ std::string Chat::LevelListMessage(std::optional<Level> current, PriorityQueso l
ss << online.size() + (current ? 1 : 0)
<< " online level(s) in the queue: ";

std::string starter = current ? std::string(current->submitter + " (current)") : "";

ss << std::accumulate(online.begin(), online.end(),
std::string(current->submitter + " (current)"),
starter,
[](std::string acc, Level x){
return acc + ", " + x.submitter;
});
Expand All @@ -151,7 +154,7 @@ std::string Chat::NextLevelMessage(std::optional<Level> l) {
}

std::stringstream ss;
ss << "Next up in queue is " << l->levelCode << ", submitted by "
ss << "Next is " << l->levelCode << ", submitted by "
<< l->submitter;
return ss.str();
}
Expand All @@ -177,7 +180,7 @@ std::string Chat::PositionMessage(int position) {
msg << "Your level is being played right now!";
break;
default:
msg << "You are currently in position " << position+1;
msg << "You are currently in position " << position;
break;
}
return msg.str();
Expand Down Expand Up @@ -235,6 +238,14 @@ void Chat::HandleMessage(std::stringstream message, std::string sender) {
WriteMessage(NextLevelMessage(l));
} else if (command == "current") {
WriteMessage(CurrentLevelMessage(_qq.Current()));
} else if (command == "random" && sender == Auth::channel) {
_timer.Reset();
std::optional<Level> l = _qq.Random();
if (l) {
WriteMessage(std::string("/marker " + l->levelCode + ", submitted by "
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this done with a method in Twitch right now? Better not duplicate the code, especially since we know this approach doesn't work.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a stub, but the actual code we've tried is here and in Next. I suppose we could leave it out.

+ l->submitter));
}
WriteMessage(NextLevelMessage(l));
} else if (command == "list") {
WriteMessage(LevelListMessage(_qq.Current(), _qq.List()));
} else if (command == "position") {
Expand Down
3 changes: 2 additions & 1 deletion chat.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

class Chat {
public:
Chat(const QuesoQueue &qq, const Timer &timer);
Chat(const QuesoQueue &qq, const Twitch &twitch, const Timer &timer);
void HandleMessage(std::stringstream message, std::string sender);
void WriteMessage(std::string message);
void Write(std::string command);
Expand All @@ -30,6 +30,7 @@ class Chat {

bool _canAddToQueue = true;
QuesoQueue _qq;
Twitch _twitch;
Timer _timer;
std::string _priorityText;

Expand Down
2 changes: 1 addition & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ int main(int, char **) {
QuesoQueue qq(t);
qq.LoadLastState();
Timer ti;
Chat c(qq, ti);
Chat c(qq, t, ti);
c.Connect();
c.Listen();
}
49 changes: 41 additions & 8 deletions quesoqueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <algorithm>
#include <iostream>
#include <fstream>
#include <random>
#include <regex>
#include <sstream>
#include <tuple>
Expand Down Expand Up @@ -58,19 +59,15 @@ std::string QuesoQueue::Add(Level level) {
if (result == _levels.end() || level.submitter == Auth::channel) {
auto online_levels = std::get<0>(List()).size();
// push to the end of the queue
if (_levels.empty() && !Current().has_value()) {
_current = std::make_optional(level);
} else {
_levels.push_back(level);
online_levels++;
}
_levels.push_back(level);
online_levels++;
std::stringstream ss;
// Since they JUST added it, we can pretty safely assume they're online.
ss << level.submitter;
ss << ", ";
ss << level.levelCode;
ss << " has been added to the queue. Currently in position #";
ss << online_levels + 1;
ss << online_levels + (_current ? 1 : 0);
ss << ".";
SaveState();
return ss.str();
Expand Down Expand Up @@ -169,7 +166,7 @@ int QuesoQueue::Position(std::string username) {
for (Level l : both) {
position++;
if (l.submitter == username) {
return position;
return position + (_current ? 1 : 0);
}
}
// not in queue
Expand Down Expand Up @@ -225,6 +222,42 @@ std::optional<Level> QuesoQueue::Current() {
return _current;
}

std::optional<Level> QuesoQueue::Random() {
auto list = List();
std::deque<Level> levels(std::get<0>(list)); // Use online levels first.

if (levels.empty()) {
levels = std::get<1>(list); // See if there are offline levels.
if (levels.empty()) {
_current = std::nullopt;
return _current;
}
}
std::vector<Level> new_current = {};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is current in a vector?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it's because you're trying to use std::sample. This seems weird, why not just generate an index and not use the extra vector? This leads to weird stuff like "new_current[0]"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, what can I say? I like using these standard functions for things where I can accidentally insert bugs without realizing (https://stackoverflow.com/a/6943003).

std::sample(levels.begin(), levels.end(), std::back_inserter(new_current),
1, std::mt19937{std::random_device{}()});

if (new_current.empty()) {
_current = std::nullopt;
} else {
_current = std::make_optional(new_current[0]);
}

// Remove current (it's in a special current place now)
_levels.erase(
std::find_if(
_levels.begin(),
_levels.end(),
[&](auto l){
return l.submitter == _current->submitter &&
l.levelCode == _current->levelCode;
}
)
);
SaveState();
return _current;
}

PriorityQueso QuesoQueue::List() {
std::deque<Level> online, offline;
std::set<std::string> online_users = _twitch.getOnlineUsers(Auth::channel);
Expand Down
7 changes: 6 additions & 1 deletion quesoqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ class QuesoQueue {
*/
std::optional<Level> Punt();

/**
* Selects a random level from the queue and returns the new top (subject to priority queue split)
*/
std::optional<Level> Random();

/**
* Split the stored level queue into online and offline for printing
*/
Expand All @@ -65,5 +70,5 @@ class QuesoQueue {
std::deque<Level> _levels;
std::optional<Level> _current;
Twitch _twitch; // query online state
const size_t maxSize = 15;
const size_t maxSize = 30;
};
20 changes: 20 additions & 0 deletions twitch.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#include "twitch.h"

#include <chrono>
#include <ctime>
#include <curl/curl.h>
#include <iostream>
#include <iomanip>
#include <map>
#include <string>
#include "SimpleJSON/JSON.h"

Expand Down Expand Up @@ -67,9 +71,25 @@ std::set<std::string> Twitch::getOnlineUsers(const std::string& channel) {
}
}

auto current_time = std::chrono::system_clock::now();
auto user_snapshot = _recent_chatters;
_recent_chatters = {};
for(auto const& [user, last_heard_from] : user_snapshot) {
//TODO: This time should be runtime configurable.
if (current_time - last_heard_from < std::chrono::minutes(5)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a TODO that this should be runtime-configurable

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

online_users.emplace(user);
_recent_chatters.emplace(user, last_heard_from);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, it seems like it might be a little extra - do we really need to clean it up? Even a few hundred independent viewers per run isn't so bad in one map.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you can replace these two lines with a call to markAsOnline() too.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, but this does use a different time than markAsOnline. Also, the first line can't be replaced, only the second.

}
}

return online_users;
}

void Twitch::markAsOnline(std::string username) {
auto current = std::chrono::system_clock::now();
_recent_chatters.emplace(username, current);
}

void placeStreamMarker() {
// stub
}
6 changes: 6 additions & 0 deletions twitch.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#pragma once

#include <chrono>
#include <ctime>
#include <map>
#include <set>
#include <string>

Expand All @@ -9,6 +12,9 @@ class Twitch {
std::set<std::string> getOnlineUsers(const std::string& channel);
void placeStreamMarker();

void markAsOnline(std::string username);

private:
std::map<std::string, std::chrono::system_clock::time_point> _recent_chatters;
// IDK twitch API keys??????
};