From: Steinar H. Gunderson Date: Mon, 28 Feb 2005 23:20:25 +0000 (+0000) Subject: Added a "top 5 chosen songs this tournament" screen. X-Git-Url: https://git.sesse.net/?p=ccbs;a=commitdiff_plain;h=723136532e3bb8b318b595b9eeef031275d5c72e Added a "top 5 chosen songs this tournament" screen. --- diff --git a/bigscreen/Makefile b/bigscreen/Makefile index 33e8478..ec59011 100644 --- a/bigscreen/Makefile +++ b/bigscreen/Makefile @@ -8,8 +8,8 @@ LIBS=$(shell freetype-config --libs) $(shell libpq3-config) -lpqxx tinyptc/libti CCBS_BIGSCREEN_SQL_OBJS=fetch_current_tournament.o fetch_list_of_active_groups.o \ fetch_max_score_for_songs.o fetch_max_score_for_players.o fetch_group.o \ fetch_needs_update.o fetch_highscore.o fetch_top_scores_for_tournament.o \ - fetch_auxilliary_screens.o -CCBS_BIGSCREEN_SCREEN_OBJS=groupscreen.o top10scorescreen.o splitscreen.o rotatescreen.o screen.o + fetch_top_chosen_songs_for_tournament.o fetch_auxilliary_screens.o +CCBS_BIGSCREEN_SCREEN_OBJS=groupscreen.o top10scorescreen.o top5chosenscreen.o splitscreen.o rotatescreen.o screen.o CCBS_BIGSCREEN_MAIN_OBJS=ccbs_bigscreen.o flagtrigger.o widestring.o fonts.o CCBS_BIGSCREEN_OBJS=$(CCBS_BIGSCREEN_SQL_OBJS) $(CCBS_BIGSCREEN_SCREEN_OBJS) $(CCBS_BIGSCREEN_MAIN_OBJS) diff --git a/bigscreen/ccbs_bigscreen.cpp b/bigscreen/ccbs_bigscreen.cpp index 8a858d3..5830356 100644 --- a/bigscreen/ccbs_bigscreen.cpp +++ b/bigscreen/ccbs_bigscreen.cpp @@ -13,6 +13,7 @@ #include "fonts.h" #include "groupscreen.h" #include "top10scorescreen.h" +#include "top5chosenscreen.h" #include "splitscreen.h" #include "rotatescreen.h" @@ -64,6 +65,10 @@ void init(pqxx::connection &conn) aux_screen->add_screen(new Top10ScoreScreen(conn, active_tournament.id)); continue; } + if (*i == widestring("top5chosen")) { + aux_screen->add_screen(new Top5ChosenScreen(conn, active_tournament.id)); + continue; + } std::fprintf(stderr, "Foobarbaz?\n"); } diff --git a/bigscreen/fetch_top_chosen_songs_for_tournament.cpp b/bigscreen/fetch_top_chosen_songs_for_tournament.cpp new file mode 100644 index 0000000..d6f7078 --- /dev/null +++ b/bigscreen/fetch_top_chosen_songs_for_tournament.cpp @@ -0,0 +1,33 @@ +#include "fetch_top_chosen_songs_for_tournament.h" + +// small utility function so we can stick TopChosenSongs in a std::set +bool TopChosen::operator< (const TopChosen &other) const +{ + if (title != other.title) + return (title < other.title); + return (frequency < other.frequency); +} + +FetchTopChosenSongsForTournament::FetchTopChosenSongsForTournament(unsigned tournament, unsigned num, std::vector *chosen) + : tournament(tournament), num(num), chosen(chosen) {} + +void FetchTopChosenSongsForTournament::operator() (pqxx::transaction<> &t) +{ + chosen->erase(chosen->begin(), chosen->end()); + + // Again, this will break if a song has more than one short title + pqxx::result res( t.exec( + "SELECT title, shorttitle, COUNT(*) AS frequency FROM scores NATURAL JOIN songs NATURAL LEFT JOIN songshorttitles WHERE tournament=" + + pqxx::to_string(tournament) + " AND chosen='t' AND song is NOT NULL GROUP BY title,shorttitle ORDER BY COUNT(*) DESC LIMIT " + + pqxx::to_string(num)) ); + + for (pqxx::result::const_iterator i = res.begin(); i != res.end(); ++i) { + TopChosen ts; + + ts.title = i["title"].as(ts.title); + ts.shorttitle = i["shorttitle"].as(ts.shorttitle); + ts.frequency = i["frequency"].as(ts.frequency); + + chosen->push_back(ts); + } +} diff --git a/bigscreen/fetch_top_chosen_songs_for_tournament.h b/bigscreen/fetch_top_chosen_songs_for_tournament.h new file mode 100644 index 0000000..9b177bf --- /dev/null +++ b/bigscreen/fetch_top_chosen_songs_for_tournament.h @@ -0,0 +1,26 @@ +#ifndef _FETCH_TOP_CHOSEN_SONGS_FOR_TOURNAMENT_H +#define _FETCH_TOP_CHOSEN_SONGS_FOR_TOURNAMENT_H 1 + +#include +#include +#include "widestring.h" + +struct TopChosen { + widestring title, shorttitle; + unsigned frequency; + + bool operator< (const TopChosen &other) const; +}; + +/* A transactor that fetches the best N scores for a given tournament */ +class FetchTopChosenSongsForTournament : public pqxx::transactor<> { +private: + unsigned tournament, num; + std::vector *chosen; + +public: + FetchTopChosenSongsForTournament(unsigned tournament, unsigned num, std::vector *chosen); + void operator() (pqxx::transaction<> &t); +}; + +#endif /* !defined(_FETCH_TOP_CHOSEN_SONGS_FOR_TOURNAMENT_H) */ diff --git a/bigscreen/top5chosenscreen.cpp b/bigscreen/top5chosenscreen.cpp new file mode 100644 index 0000000..3110684 --- /dev/null +++ b/bigscreen/top5chosenscreen.cpp @@ -0,0 +1,76 @@ +#include +#include + +#include "top5chosenscreen.h" +#include "fonts.h" + +Top5ChosenScreen::Top5ChosenScreen(pqxx::connection &conn, unsigned tournament) + : conn(conn), tournament(tournament), scores_changed(conn, "scores"), valid(false) +{ +} + +Top5ChosenScreen::~Top5ChosenScreen() +{ +} + +bool Top5ChosenScreen::check_invalidated() +{ + if (!valid) + return true; + if (!scores_changed.get_flag()) + return false; + + return true; +} + +void Top5ChosenScreen::draw(unsigned char *buf) +{ + scores_changed.reset_flag(); + memset(buf, 0, 800 * 600 * 4); + + // fetch the top 5 chosen songs + std::vector scores; + conn.perform(FetchTopChosenSongsForTournament(tournament, 5, &scores)); + + { + unsigned width = my_draw_text("Today's top 5 chosen songs", NULL, 40.0); + my_draw_text("Today's top 5 chosen songs", buf, 40.0, 800/2 - width/2, 60); + } + + // simple headings + my_draw_text("Song", buf, 12.0, 70, 100); + my_draw_text("Frequency", buf, 12.0, 710, 100); + + unsigned row = 1, y = 140; + for (std::vector::const_iterator i = scores.begin(); i != scores.end(); ++i) { + char str[16]; + unsigned r = 255, g = 255, b = 255; + + // print new entries in red + if (seen_topchosen.count(*i) == 0 && seen_topchosen.size() > 0) { + g = b = 0; + } + + std::sprintf(str, "%u", row++); + unsigned width = my_draw_text(str, NULL, 24.0); + my_draw_text(str, buf, 24.0, 30 - width/2, y); + + if (my_draw_text(i->title, NULL, 24.0) > 610) { + my_draw_text(i->shorttitle, buf, 24.0, 70, y, r, g, b); + } else { + my_draw_text(i->title, buf, 24.0, 70, y, r, g, b); + } + + std::sprintf(str, "%u", i->frequency); + width = my_draw_text(str, NULL, 24.0); + my_draw_text(str, buf, 24.0, 728 - width/2, y, r, g, b); + + y += 40; + } + + valid = true; + + seen_topchosen.erase(seen_topchosen.begin(), seen_topchosen.end()); + std::copy(scores.begin(), scores.end(), std::inserter(seen_topchosen, seen_topchosen.end())); +} + diff --git a/bigscreen/top5chosenscreen.h b/bigscreen/top5chosenscreen.h new file mode 100644 index 0000000..af2df73 --- /dev/null +++ b/bigscreen/top5chosenscreen.h @@ -0,0 +1,28 @@ +#ifndef _TOP5CHOSENSCREEN_H +#define _TOP5CHOSENSCREEN_H 1 + +#include +#include + +#include "screen.h" +#include "flagtrigger.h" +#include "fetch_top_chosen_songs_for_tournament.h" + +/* A screen class showing a group in the tournament */ +class Top5ChosenScreen : public GenericScreen { +private: + pqxx::connection &conn; + unsigned tournament; + FlagTrigger scores_changed; + bool valid; + std::set seen_topchosen; + +public: + Top5ChosenScreen(pqxx::connection &conn, unsigned tournament); + virtual ~Top5ChosenScreen(); + + bool check_invalidated(); + void draw(unsigned char *buf); +}; + +#endif /* !defined(_TOP5CHOSENSCREEN_H) */