Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • bootstrap4
  • intros
  • master
  • modules
  • postgres_integration
  • s3compatible
6 results

Target

Select target project
  • jannik/website
  • vincent/website
  • dominic/website
  • romank/website
  • videoaginfra/website
5 results
Select Git revision
  • bootstrap4
  • forbid-save-as
  • intros
  • live_sources
  • master
  • modules
  • moodle-integration
  • patch-double-tap-seek
  • patch_datum_anzeigen
  • patch_raum_anzeigen
  • upload-via-token
11 results
Show changes
from server import *
from datetime import time
@register_navbar('personalisierter Drehplan', icon='calendar', userendpoint=True, endpoint='timetable_user')
@register_navbar('Drehplan', icon='calendar')
@app.route('/internal/timetable')
@app.route('/internal/user/<int:user>/timetable', endpoint='timetable_user')
@mod_required
def timetable(user=None):
if 'kw' not in request.args:
if 'date' in request.args:
thisweekmonday = datetime.now()
thisweekmonday -= timedelta(days=thisweekmonday.weekday())
def get_monday(day):
return day-timedelta(days=day.weekday())
def get_week_offset(value):
if value is None:
return 0
day = None
for pattern in ['%d-%m-%Y-1', '%Y-W%W-%w']:
try:
datesweekmonday = datetime.strptime(request.args['date'], '%d-%m-%Y')
except ValueError:
datesweekmonday = None
if not datesweekmonday:
try:
datesweekmonday = datetime.strptime(request.args['date'] + '-1', "%Y-W%W-%w")
day = datetime.strptime(value+'-1', pattern)
except ValueError:
datesweekmonday = None
pass
if day is not None:
break
if day is None:
return 0
return int((get_monday(day) - get_monday(datetime.now())).days/7)
if not datesweekmonday:
kw = 0
else:
datesweekmonday -= timedelta(days=datesweekmonday.weekday())
kw = int((datesweekmonday.date() - thisweekmonday.date()).days/7)
else:
kw=0
else:
kw=int(request.args['kw'])
try:
start = date.today() - timedelta(days=date.today().weekday() -7*kw)
except:
start = date.today() - timedelta(days=date.today().weekday())
weekofyear = '{}-W{:02d}'.format(datetime.today().year, datetime.today().isocalendar()[1])
days = [{'date': start, 'lectures': [], 'atonce':0, 'index': 0 }]
earlieststart=time(23,59)
latestend=time(0,0)
for i in range(1,7):
days.append({'date': days[i-1]['date'] + timedelta(days=1), 'atonce':0, 'index': i, 'lectures':[] })
for i in days:
# date and times are burning in sqlite
s = datetime.combine(i['date'],time(0,0))
e = datetime.combine(i['date'],time(23,59))
i['lectures'] = []
for l in query ('''
SELECT lectures.*, courses.short, "course" AS sep, courses.*
def query_lectures_on_day(start, end):
# What we want to match:
# lecture.time <= end AND lecture.time+lecture.duration >= start
# But there is no SQL statement that does this and is compatible with both sqlite
# and mysql, so we approximate the "lecture.time+lecture.duration" part
rows = query('''SELECT lectures.*, courses.short, \'course\' AS sep, courses.*
FROM lectures
JOIN courses ON (lectures.course_id = courses.id)
WHERE time < ? AND time > ? AND NOT norecording AND NOT external
ORDER BY time ASC''', i['date']+timedelta(weeks=2), i['date']-timedelta(weeks=2)):
# we can not use the where clause of sql to match against the time, because sqlite and mysql use a different syntax -.-
# we still use it to only get the lectures for a 3 week periode
if not l['time']:
l['time'] = datetime.fromtimestamp(0)
if ((l['time'] < e) and (l['time'] > s)) or ((l['time'] + timedelta(minutes=l['duration']) < e) and (l['time'] + timedelta(minutes=l['duration'])> s)):
# filter on responsible user if a user parameter was given
l['responsible'] = query('''SELECT users.*
FROM responsible
JOIN users ON (responsible.user_id = users.id AND responsible.course_id = ?)
ORDER BY users.realname ASC''', l['course_id'])
if len(l['responsible']) == 0:
l['responsible'] = [{"realname": "Niemand", "id": -1}]
if not user or user in [ r['id'] for r in l['responsible'] ]:
i['lectures'].append(l)
WHERE time <= ? AND time > ?
ORDER BY time ASC''', end, start-timedelta(weeks=2))
lectures = []
for lecture in rows:
if lecture['time']+timedelta(minutes=lecture['duration']) >= start:
lectures.append(lecture)
return lectures
oldtime = l['time']
l['time'] = max(s,l['time'])
l['duration'] = ( min(e,oldtime + timedelta(minutes=l['duration'])) - l['time'] ).total_seconds()/60
# sweepline to find out how many lectures overlap
maxcol=0;
curcol=0;
freecol=[];
for l in i['lectures']:
# who the hell inserts lectures with zero length?!?!?
l['time_end'] = l['time']+timedelta(minutes=max(l['duration'],1))
# create sweepline input array
sweeplinetupels = [(l['time'],True,l) for l in i['lectures']]
sweeplinetupels += [(l['time_end'],False,l) for l in i['lectures']]
tmp = []
for x in sweeplinetupels:
unique = True
for y in tmp:
if x[0] == y[0] and x[1] == y[1] and x[2]['short'] == y[2]['short']:
unique = False
if unique:
tmp.append(x)
'''Use a sweepline algorithm to find overlapping lectures
sweeplinetupels = sorted(tmp, key=lambda t:(t[0],t[1]))
for l in sweeplinetupels:
if l[1]:
For each day the item 'maxcol' will be the number of columns required to display
the overlapping lectures. For each lecture the item 'timetable_col' will be the
index of the column the lecture is going to be rendered in.'''
def timetable_sweepline(days):
earliest_start = time(23, 59)
latest_end = time(0, 0)
for day in days:
sweeplinetupels = [(lecture['time'].time(), True, lecture) for lecture in day['lectures']]
sweeplinetupels += [(lecture['time_end'].time(), False, lecture) for lecture in day['lectures']]
maxcol = 0
curcol = 0
freecol = []
sweeplinetupels.sort(key=lambda row: row[:2])
for timestamp, is_start, lecture in sweeplinetupels:
if is_start:
curcol += 1
if curcol > maxcol:
maxcol = curcol
if len(freecol) == 0:
freecol.append(maxcol)
l[2]['timetable_col'] = freecol.pop()
if earlieststart > l[0].time():
earlieststart = l[0].time()
maxcol = max(maxcol, curcol)
if freecol:
lecture['timetable_col'] = freecol.pop()
else:
lecture['timetable_col'] = maxcol
earliest_start = min(earliest_start, timestamp)
else:
curcol -= 1
freecol.append(l[2]['timetable_col'])
if latestend < l[0].time():
latestend = l[0].time()
i['maxcol'] = max(maxcol,1)
times=[]
s = min(earlieststart,time(8,0))
e = max(latestend,time(19,0))
for i in range(s.hour*4,min(int((60*e.hour/15)/4)*4+5,24*4)):
t = i*15
times.append(time(int(t/60),t%60))
return render_template('timetable.html',days=days,times=times,kw=kw, weekofyear=weekofyear, user=query('SELECT * FROM users WHERE id = ?', user)[0] if user else None)
freecol.append(lecture['timetable_col'])
latest_end = max(latest_end, timestamp)
day['maxcol'] = max(maxcol, 1)
return earliest_start, latest_end
@register_navbar('personalisierter Drehplan', icon='calendar', userendpoint=True, endpoint='timetable_user')
@register_navbar('Drehplan', icon='calendar')
@app.route('/internal/timetable')
@app.route('/internal/user/<int:user>/timetable', endpoint='timetable_user')
@mod_required
def timetable(user=None):
if 'kw' in request.args:
week_offset = int(request.args['kw'])
else:
week_offset = get_week_offset(request.args.get('date', None))
start_day = date.today() - timedelta(days=date.today().weekday() - 7*week_offset)
days = [{'date': start_day, 'lectures': [], 'atonce': 0, 'index': 0}]
for i in range(1, 7):
days.append({'date': days[i-1]['date'] + timedelta(days=1), 'atonce': 0, 'index': i, 'lectures': []})
for day in days:
start = datetime.combine(day['date'], time(0, 0))
end = datetime.combine(day['date'], time(23, 59))
day['lectures'] = []
for lecture in query_lectures_on_day(start, end):
lecture['time_end'] = lecture['time']+timedelta(minutes=lecture['duration'])
# "Crop" lecture's timespan to start/end of day
lecture['time'] = max(start, lecture['time'])
lecture['time_end'] = min(end, lecture['time_end'])
# Ensure length > 0
lecture['time_end'] = max(lecture['time_end'], lecture['time']+timedelta(minutes=1))
lecture['duration'] = int((lecture['time_end'] - lecture['time']).total_seconds()/60)
# Filter on responsible user if a user parameter was given
lecture['responsible'] = query('''SELECT users.*
FROM responsible
JOIN users ON (responsible.user_id = users.id AND responsible.course_id = ?)
ORDER BY users.realname ASC''', lecture['course_id'])
if len(lecture['responsible']) == 0:
lecture['responsible'] = [{"realname": "Niemand", "id": -1}]
if not user or user in [r['id'] for r in lecture['responsible']]:
day['lectures'].append(lecture)
earliest_start, latest_end = timetable_sweepline(days)
start = min(earliest_start, time(8, 0))
end = max(latest_end, time(19, 0))
blocks = []
for i in range(start.hour*4, min(int((60*end.hour/15)/4)*4+5, 24*4)):
timestamp = i*15
blocks.append(time(int(timestamp/60), timestamp%60))
weekofyear = '{}-W{:02d}'.format(datetime.today().year, datetime.today().isocalendar()[1])
return render_template('timetable.html',
days=days,
blocks=blocks,
kw=week_offset,
weekofyear=weekofyear,
user=query('SELECT * FROM users WHERE id = ?', user)[0] if user else None)