Skip to content
Draft
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
30 changes: 30 additions & 0 deletions backend/ranker.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,34 @@ def score_schedule(schedule, preferences):
overload += (count - limit)
score -= overload * 5.0 # Heavy penalty

# 5. Day Max Limit (Specific Days)
if preferences.get('day_max_limit_enabled'):
limit = preferences.get('day_max_limit_value', 4)
target_days = preferences.get('day_max_limit_days', []) # List of bools, idx 0=Mon

penalty = 0
# Ensure target_days has 7 elements
if len(target_days) < 7:
target_days = target_days + [False] * (7 - len(target_days))

for w in range(1, 26):
mask = full_bitmap[w]
if mask == 0: continue

for d in range(7):
# Check if this day is selected for limiting
if not target_days[d]:
continue

day_bits = (mask >> (d * 13)) & 0x1FFF
count = bin(day_bits).count('1')

if count > limit:
# Penalty calculation
# If limit is 0 (day off), any class is bad.
diff = count - limit
penalty += diff * 50.0 # Very heavy penalty

score -= penalty

return score
19 changes: 17 additions & 2 deletions static/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ createApp({
avoid_early_morning: false,
avoid_weekend: false,
compactness: 'none',
max_daily_load: 0
max_daily_load: 0,
day_max_limit_enabled: false,
day_max_limit_value: 4,
day_max_limit_days: [true, true, true, true, true, true, true]
});

const filterText = ref('');
Expand Down Expand Up @@ -89,6 +92,18 @@ createApp({
visible.forEach(c => c.checked = !allChecked);
};

const toggleAllDays = (select) => {
for(let i=0; i<7; i++) {
preferences.day_max_limit_days[i] = select;
}
};

const invertDays = () => {
for(let i=0; i<7; i++) {
preferences.day_max_limit_days[i] = !preferences.day_max_limit_days[i];
}
};

// --- Import Logic ---

const openImportModal = () => {
Expand Down Expand Up @@ -332,7 +347,7 @@ createApp({
filterText, hasSearched, filteredSearchResults,
doSearch, createGroup, getGroupName, getActiveCount, toggleCandidate, removeGroup,
generateSchedules, getCell, downloadImage, saveSession, newSession, toastRef,
toggleSelectAll,
toggleSelectAll, toggleAllDays, invertDays,
showImportModal, importText, isImporting, importStatus, importParams,
openImportModal, closeImportModal, startBatchImport
};
Expand Down
32 changes: 31 additions & 1 deletion static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,37 @@ <h3>偏好设置</h3>
<option value="low">分散 (均匀分布)</option>
</select>
</div>
<div style="margin-top: 10px;">

<div style="margin-top: 15px; border-top: 1px solid #eee; padding-top: 10px;">
<label style="font-weight: bold;">
<input type="checkbox" v-model="preferences.day_max_limit_enabled">
日最多节数限制
</label>

<div v-if="preferences.day_max_limit_enabled" style="margin-top: 10px; margin-left: 20px; padding: 10px; background: #f9f9f9; border-radius: 4px;">
<div style="margin-bottom: 10px;">
限制为:
<select v-model.number="preferences.day_max_limit_value" style="width: auto; display: inline-block;">
<option :value="0">0 (没课)</option>
<option :value="2">2</option>
<option :value="4">4</option>
<option :value="6">6</option>
</select> 节
</div>
<div>
适用日期:
<button class="secondary" style="padding: 2px 8px; margin-right: 5px; font-size: 0.8rem;" @click="toggleAllDays(true)">全选</button>
<button class="secondary" style="padding: 2px 8px; font-size: 0.8rem;" @click="invertDays()">反选</button>
</div>
<div style="display: flex; gap: 10px; flex-wrap: wrap; margin-top: 5px;">
<label v-for="(day, idx) in ['一','二','三','四','五','六','日']" :key="idx" style="cursor: pointer;">
<input type="checkbox" v-model="preferences.day_max_limit_days[idx]"> 周{{ day }}
</label>
</div>
</div>
</div>

<div style="margin-top: 20px;">
<button @click="generateSchedules" style="width: 100%; padding: 15px; font-size: 1.1rem;">生成课表方案</button>
</div>
</div>
Expand Down