initial commit

This commit is contained in:
NeilClack
2026-08-07 14:51:41 -05:00
commit 9251b3a196
604 changed files with 464448 additions and 0 deletions
+165
View File
@@ -0,0 +1,165 @@
#include "scroller_streams.h"
#include "db/database_manager.h"
#include <gtest/gtest.h>
#include <string>
#include <unordered_map>
#include <vector>
namespace {
using radiantwave::db::AudioFileRecord;
using radiantwave::db::ProclamationRecord;
using radiantwave::scroller::ProclamationStream;
using radiantwave::scroller::StreamColor;
using radiantwave::scroller::buildStreams;
using radiantwave::scroller::kDefaultRepeatCount;
using radiantwave::scroller::kSelectedRepeatCount;
const std::string kDefaultId = "default";
std::vector<StreamColor> palette()
{
StreamColor c;
c.r = 10;
c.g = 20;
c.b = 30;
return {c};
}
} // namespace
TEST(ScrollerStreamsTest, InterleavesSelectedWithDefault)
{
ProclamationRecord p1;
p1.id = "one";
p1.title = "One";
p1.content = "hello world";
p1.selected = true;
p1.solfeggio_frequency_id = 2;
ProclamationRecord p2;
p2.id = "two";
p2.title = "Two";
p2.content = "foo bar baz";
p2.selected = true;
p2.solfeggio_frequency_id = 5;
ProclamationRecord def;
def.id = kDefaultId;
def.title = "Default";
def.content = "default text";
def.selected = true;
def.solfeggio_frequency_id = 5;
std::unordered_map<int, std::vector<StreamColor>> palettes;
palettes[2] = palette();
std::unordered_map<int, AudioFileRecord> audio;
AudioFileRecord af;
af.id = 1;
af.filename = "396Hz.wav";
af.solfeggio_frequency_id = 2;
audio[2] = af;
auto streams = buildStreams({p1, p2, def}, palettes, palette(), audio, kDefaultId);
// The first user-selected proclamation plays first, followed by the
// default, then the next selected, then the default again.
ASSERT_EQ(streams.size(), 4u);
EXPECT_EQ(streams[0].name, "One");
ASSERT_EQ(streams[0].words.size(), 2u);
EXPECT_EQ(streams[0].words[0], "hello");
EXPECT_EQ(streams[0].words[1], "world");
EXPECT_EQ(streams[0].repeat, kSelectedRepeatCount);
EXPECT_EQ(streams[0].solfeggio_frequency_id, 2);
EXPECT_EQ(streams[0].audioFilename, "396Hz.wav");
EXPECT_EQ(streams[0].palette.size(), 1u);
EXPECT_EQ(streams[1].name, "Default");
EXPECT_EQ(streams[1].repeat, kDefaultRepeatCount);
EXPECT_EQ(streams[1].solfeggio_frequency_id, 5);
EXPECT_EQ(streams[1].audioFilename, "OriginalAudio.wav"); // no audio for freq 5
EXPECT_EQ(streams[1].palette.size(), 1u); // falls back to 528 palette
EXPECT_EQ(streams[2].name, "Two");
EXPECT_EQ(streams[2].repeat, kSelectedRepeatCount);
EXPECT_EQ(streams[2].palette.size(), 1u); // falls back to 528 palette
EXPECT_EQ(streams[3].name, "Default");
EXPECT_EQ(streams[3].repeat, kDefaultRepeatCount);
EXPECT_EQ(streams[3].audioFilename, "OriginalAudio.wav");
}
TEST(ScrollerStreamsTest, DefaultOnlyWhenNothingSelected)
{
ProclamationRecord p1;
p1.id = "one";
p1.title = "One";
p1.content = "x";
p1.selected = false;
ProclamationRecord def;
def.id = kDefaultId;
def.title = "Default";
def.content = "y";
def.selected = true;
auto streams = buildStreams({p1, def}, {}, palette(), {}, kDefaultId);
ASSERT_EQ(streams.size(), 1u);
EXPECT_EQ(streams[0].name, "Default");
EXPECT_EQ(streams[0].repeat, kDefaultRepeatCount);
}
TEST(ScrollerStreamsTest, MissingDefaultStillStreamsSelected)
{
ProclamationRecord p1;
p1.id = "one";
p1.title = "One";
p1.content = "x";
p1.selected = true;
auto streams = buildStreams({p1}, {}, palette(), {}, kDefaultId);
ASSERT_EQ(streams.size(), 1u);
EXPECT_EQ(streams[0].name, "One");
EXPECT_EQ(streams[0].repeat, kSelectedRepeatCount);
}
TEST(ScrollerStreamsTest, SplitsGluedSentencePunctuation)
{
ProclamationRecord p1;
p1.id = "one";
p1.title = "One";
p1.content = "state?Create NOW?KING field’s fine (Acts 17:27)I example.com";
p1.selected = true;
auto streams = buildStreams({p1}, {}, palette(), {}, kDefaultId);
ASSERT_EQ(streams.size(), 1u);
const auto& words = streams[0].words;
// "?" glued to an uppercase word splits after the punctuation, keeping the
// sentence separator attached to the preceding word.
EXPECT_EQ(words[0], "state?");
EXPECT_EQ(words[1], "Create");
EXPECT_EQ(words[2], "NOW?");
EXPECT_EQ(words[3], "KING");
// Curly apostrophes are not sentence punctuation and stay inside the word.
EXPECT_EQ(words[4], "field’s");
EXPECT_EQ(words[5], "fine");
// Closing paren followed by an uppercase letter splits so the verse
// reference and the next word are separate tokens.
EXPECT_EQ(words[6], "(Acts");
EXPECT_EQ(words[7], "17:27)");
EXPECT_EQ(words[8], "I");
// A lowercase continuation after a dot is not a new sentence, so this
// stays intact.
EXPECT_EQ(words[9], "example.com");
}