First Commit

This commit is contained in:
xiaolinquan committed 2026-11-06 01:04:35 +08:00
commit 3796ec5cd2
146 files changed
+4825

No files matched your search

+72
View File
@@ -0,0 +1,72 @@
#include "roster.h"
#include <QSet>
namespace Roster {
ParsedNames parse(const QString &text)
{
ParsedNames result;
QSet<QString> seen;
const QStringList lines = text.split(QLatin1Char('\n'));
int lineNumber = 0;
for (const QString &line : lines) {
++lineNumber;
const QString name = line.trimmed();
if (name.isEmpty()) continue;
if (seen.contains(name)) {
result.error = QStringLiteral("第 %1 行与前面的条目重复:%2。"
"同名学生请加上学号后再应用名单。").arg(lineNumber).arg(name);
return result;
}
if (name.size() > 100) {
result.error = QStringLiteral("第 %1 行超过 100 个字符,请检查是否粘贴了整段文字。")
.arg(lineNumber);
return result;
}
seen.insert(name);
result.names.append(name);
}
if (result.names.isEmpty())
result.error = QStringLiteral("名单为空,请每行输入一位学生。");
else if (result.names.size() > 5000)
result.error = QStringLiteral("名单超过 5000 人,请分批操作。");
return result;
}
void Session::setNames(const QStringList &names)
{
m_names = names;
resetDraw();
}
void Session::resetDraw() { m_pool = m_names; }
QStringList Session::draw(int count, QRandomGenerator &random)
{
QStringList selected;
if (count <= 0 || count > m_pool.size()) return selected;
for (int i = 0; i < count; ++i) {
const int index = random.bounded(static_cast<int>(m_pool.size()));
// 从候选池中移除已抽到的人,本轮后续抽签就不会重复。
selected.append(m_pool.takeAt(index));
}
return selected;
}
QList<QStringList> Session::groups(int value, bool valueIsGroupCount,
QRandomGenerator &random) const
{
QList<QStringList> result;
const int n = static_cast<int>(m_names.size());
if (n == 0 || value <= 0 || (valueIsGroupCount && value > n)) return result;
const int count = valueIsGroupCount ? value : (n + value - 1) / value;
QStringList shuffled = m_names;
// Fisher–Yates 洗牌。每次从尚未固定的位置中均匀选取一个。
for (int i = n - 1; i > 0; --i)
qSwap(shuffled[i], shuffled[random.bounded(i + 1)]);
for (int i = 0; i < count; ++i) result.append(QStringList());
// 轮流放入各组,保证每人出现一次,各组人数最多相差 1。
for (int i = 0; i < n; ++i) result[i % count].append(shuffled.at(i));
return result;
}
}