diff --git a/cutprogress.py b/cutprogress.py
index c1741b1f042ea8abd2439ab16334d0fbdea3612f..0b382351241fdca61df19c6d57f5a4ab4b6c034a 100644
--- a/cutprogress.py
+++ b/cutprogress.py
@@ -1,5 +1,5 @@
 from server import *
-from datetime import time
+import datetime
 
 @register_navbar('Schnittfortschritt User', icon='spinner', iconlib='fa', userendpoint=True, endpoint='cutprogress_user')
 @register_navbar('Schnittfortschritt', icon='spinner', iconlib='fa')
@@ -7,33 +7,94 @@ from datetime import time
 @app.route('/internal/user/<int:user>/cutprogress', endpoint='cutprogress_user')
 @mod_required
 def cutprogress(user=None):
+	# use request argument, default to latest semester
 	allsemester = query('SELECT DISTINCT semester from courses ORDER BY semester DESC')
 	semester = request.values.get('semester', allsemester[0]['semester'])
-	coursesraw = query('SELECT courses.id, courses.handle, courses.short FROM courses WHERE semester = ?', semester)
-	courses = []
-	maxlecturecount = 0
-	for course in coursesraw:
-		course['lectures'] = query('''
-			SELECT lectures.title, lectures.time, lectures.id FROM lectures
-			WHERE lectures.course_id= ? AND NOT lectures.deleted AND NOT lectures.norecording
-			ORDER BY lectures.time''', course['id'])
-		for lecture in course['lectures']:
-			lecture['videos'] = query('''
-				SELECT videos.path, formats.description as formatdesc, videos.visible FROM videos
-				JOIN formats ON (videos.video_format = formats.id)
-				WHERE videos.lecture_id = ? AND NOT videos.deleted''', lecture['id'])
-		course['responsible'] = query('''SELECT users.*
-				FROM responsible
-				JOIN users ON (responsible.user_id = users.id AND responsible.course_id = ?)
-				ORDER BY users.realname ASC''', course['id'])
-		if len(course['responsible']) == 0:
-			course['responsible'] = [{"realname": "Niemand", "id": -1}]
-		if not user or user in [ r['id'] for r in course['responsible'] ]:
-			courses.append(course)
-			maxlecturecount = max(len(course['lectures']), maxlecturecount)
+
+	# filter to single user?
+	if user is not None:
+		user = query('SELECT * FROM users WHERE id = ?', user)[0]
+
+	# column headers: courses
+	courses = query('''
+		SELECT courses.id, courses.handle, courses.short, courses.responsible
+		FROM courses
+		WHERE semester = ?
+		ORDER by id DESC
+		''', semester)
+
+	# list of people responsible for course
+	for course in courses:
+		people = query('''
+			SELECT users.*
+			FROM users
+			JOIN responsible ON responsible.user_id = users.id
+			WHERE responsible.course_id = ?
+			ORDER BY users.realname ASC
+			''', course['id'])
+
+		if not people:
+			people = [{ 'realname': 'Niemand' }]
+
+		course['responsible'] = people
+
+	# fetch lectures
+	lectures = query('''
+		SELECT
+			lectures.id,
+			lectures.course_id,
+			lectures.time, DATE(lectures.time) as date,
+			lectures.title,
+			COUNT(videos.id) as videos_total,
+			COUNT(videos.visible) as videos_visible
+		FROM lectures
+		JOIN courses ON courses.id = lectures.course_id
+		LEFT JOIN videos ON lectures.id = videos.lecture_id
+		WHERE courses.semester = ?
+			AND date <= DATE('now')
+			AND NOT lectures.norecording
+		GROUP BY lectures.id
+		ORDER BY date DESC, lectures.time ASC, lectures.id ASC
+		''', semester)
+
+	# sort dates, figure out when weeks change
+	dates = sorted({
+		datetime.datetime.strptime(row['date'], '%Y-%m-%d')
+		for row in lectures
+	}, reverse=True)
+
+	# check week numbers
+	is_new_weeks = [
+		False if (i == 0) else thisdate.isocalendar()[1] != dates[i-1].isocalendar()[1]
+		for i, thisdate in enumerate(dates)
+	]
+
+	# sort into cells
+	tablebody = [
+		{
+			'date': date, # row header
+			'is_new_week': is_new_week,
+			'cells': [ # this is the body of the row
+				[ # this list is a cell
+					lecture
+					for lecture in lectures
+					if lecture['course_id'] == course['id'] and datetime.datetime.strptime(lecture['date'], '%Y-%m-%d') == date
+					and (user is None or user in [r['id'] for r in course['responsible']])
+				]
+				for course in courses
+			]
+		}
+		for date,is_new_week in zip(dates, is_new_weeks)
+	]
+
 	return render_template('cutprogress.html',
-			allsemester=allsemester,
-			semester=semester,
-			courses=courses,
-			maxlecturecount=maxlecturecount,
-			user=query('SELECT * FROM users WHERE id = ?', user)[0] if user else None)
+		# dropdown selection
+		allsemester=allsemester, # options
+		semester=semester, # choice
+		user=user,
+
+		# content
+		courses=courses,
+		dates=dates,
+		tablebody=tablebody,
+	)
diff --git a/static/style.css b/static/style.css
index becd506401df17e70822ae06b1ac844e598392b0..e2060c23287d11d3987ee1ba1ee9070964b80702 100644
--- a/static/style.css
+++ b/static/style.css
@@ -144,3 +144,7 @@ th.rotate > div {
 	max-width: 500px;
 
 }
+
+#cutprogress.table tr.weekbreak td {
+	border-top: 2px solid black !important;
+}
diff --git a/templates/cutprogress.html b/templates/cutprogress.html
index ca1ccf9c7ea906dae246e7ba1e8715ae5e05c424..6e145d2334f4a9978770a7bd1dbb62366eb172f9 100644
--- a/templates/cutprogress.html
+++ b/templates/cutprogress.html
@@ -12,8 +12,11 @@
 				</span>
 		</div>
 		<div class="panel-body table-responsive">
-			<table class="table table-condensed table-bordered">
+			<table id="cutprogress" class="table table-condensed table-bordered">
 				<tr>
+					<th class="text-left">
+						Datum
+					</th>
 				{% for course in courses %}
 					<th class="text-center rotate">
 						<div>
@@ -22,33 +25,27 @@
 					</th>
 				{% endfor %}
 				</tr>
-				{% for i in range(maxlecturecount) %}
-				<tr class="text-center">
-					{% for course in courses %}
+
+			{% for row in tablebody %}
+				<tr class="text-center {% if row.is_new_week %}weekbreak{% endif %}">
+					<td class="text-left">{{ row.date.strftime("%d.%m.%Y (%a)") }}</td>
+					{% for cell in row.cells %}
 					<td>
-						{% set l = course.lectures[i]|d({}) %}
-						{% if "time" in l %}
-						<a href="{{ url_for("course", handle=course.handle) }}#lecture-{{ l.id }}" title="{{ l.time }} &#10;Titel: {{ l.title|replace('\n','') }} &#10;Videos: {{ l.videos|count }} &#10;Internes Kommentar: {{ l.internal }}">
-							{% if l.time < datetime.now() %}
-								{% if l.videos|count == 0 %}
+						{% for lecture in cell %}
+						<a href="{{ url_for('course', handle=lecture.course_id) }}#lecture-{{ lecture.id }}" title="Uhrzeit: {{ lecture.time.strftime('%H:%M') }}&#10;Titel: {{ lecture.title|replace('\n','') }}&#10;Videos: {{ lecture.videos_total }}&#10;Interner Kommentar: {{ lecture.internal }}">
+							{% if lecture.videos_total == 0 %}
 								<span style="color: red" aria-hidden="true" class="fa fa-times"></span>
-								{% else %}
-									{% if l.videos|selectattr('visible')|list|count == 0 %}
-										<span style="color: orange" aria-hidden="true" class="glyphicon glyphicon-ok"></span>
-									{% else %}
-										<span style="color: green" aria-hidden="true" class="glyphicon glyphicon-ok"></span>
-									{% endif %}
-								{% endif %}
+							{% elif lecture.videos_visible == 0 %}
+								<span style="color: orange" aria-hidden="true" class="glyphicon glyphicon-ok"></span>
 							{% else %}
-								<span style="color: grey" aria-hidden="true" class="fa fa-times"></span>
+								<span style="color: green" aria-hidden="true" class="glyphicon glyphicon-ok"></span>
 							{% endif %}
-							</a>
-						{% else %}
-						{% endif %}
+						</a>
+						{% endfor %}
 					</td>
 					{% endfor %}
 				</tr>
-				{% endfor %}
+			{% endfor %}
 			</table>
 		</div>
 	</div>