First Commit
This commit is contained in:
commit
3796ec5cd2
146 files changed
+4825
No files matched your search
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user