Skip to content
Snippets Groups Projects
Commit ba1343da authored by YSelf Tool's avatar YSelf Tool
Browse files

Changed mode to sorting type, implemented balanced and fifo

parent 12cbdd03
No related branches found
No related tags found
No related merge requests found
...@@ -38,17 +38,17 @@ class Event(db.Model): ...@@ -38,17 +38,17 @@ class Event(db.Model):
__tablename__ = "events" __tablename__ = "events"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, unique=True) name = db.Column(db.String, unique=True)
date = db.Column(db.Date) mode = db.Column(db.String)
def __init__(self, name, date): def __init__(self, name, mode):
self.name = name self.name = name
self.date = date self.mode = mode
def __repr__(self): def __repr__(self):
return "<Event(id={}, name='{}', date={})>".format( return "<Event(id={}, name='{}', mode='{}')>".format(
self.id, self.id,
self.name, self.name,
self.date self.mode
) )
...@@ -63,7 +63,7 @@ class Speaker(db.Model): ...@@ -63,7 +63,7 @@ class Speaker(db.Model):
self.event = event self.event = event
def __repr__(self): def __repr__(self):
return "<Speaker(id={}, name={}, event={})>".format( return "<Speaker(id={}, name='{}', event={})>".format(
self.id, self.id,
self.name, self.name,
self.event self.event
......
...@@ -28,4 +28,4 @@ class AddStatementForm(Form): ...@@ -28,4 +28,4 @@ class AddStatementForm(Form):
class NewEventForm(Form): class NewEventForm(Form):
name = StringField("Name", validators=[InputRequired("Entering the name is required.")]) name = StringField("Name", validators=[InputRequired("Entering the name is required.")])
date = DateField("Date (DD.MM.YYYY)", validators=[InputRequired("Entering the date is required.")], format="%d.%m.%Y") mode = StringField("Mode", validators=[InputRequired("Entering the mode is required."), AnyOf(values=["balanced", "fifo"], message="Must be 'balanced' or 'fifo' atm.")])
...@@ -78,7 +78,7 @@ def event_new(): ...@@ -78,7 +78,7 @@ def event_new():
if Event.query.filter_by(name=form.name.data).count() > 0: if Event.query.filter_by(name=form.name.data).count() > 0:
flash("There already is an event with that name.", "alert-error") flash("There already is an event with that name.", "alert-error")
return render_layout("admin_event_new.html", form=form) return render_layout("admin_event_new.html", form=form)
event = Event(form.name.data, form.date.data) event = Event(form.name.data, form.mode.data)
db.session.add(event) db.session.add(event)
db.session.commit() db.session.commit()
return redirect(url_for(".event")) return redirect(url_for(".event"))
...@@ -118,5 +118,4 @@ def event_edit(): ...@@ -118,5 +118,4 @@ def event_edit():
@admin_permission.require() @admin_permission.require()
def event(): def event():
events = Event.query.all() events = Event.query.all()
print(events)
return render_layout("admin_event_index.html", events=events) return render_layout("admin_event_index.html", events=events)
...@@ -13,62 +13,73 @@ import config ...@@ -13,62 +13,73 @@ import config
speech = Blueprint("speech", __name__) speech = Blueprint("speech", __name__)
def transpose(arr):
print(list)
return list(map(list, zip(*arr)))
def query_statements(mode, event_id): def query_statements(mode, event_id):
statements = [] statements = db.session.query(Statement).filter_by(event=event_id).all()
if mode == "pending": speakers = db.session.query(Speaker).filter_by(event=event_id).all()
statements = db.session.query(Statement, Speaker, db.func.count(Statement.speaker).label("total")).group_by(Speaker.id).join(Speaker).filter(Statement.event == event_id).order_by("total ASC", Statement.insertion_time).all() if mode == "balanced" or mode == "pending":
elif mode == "all": count = { speaker.id: 0 for speaker in speakers }
statements = db.session.query(Statement, Speaker).join(Speaker).filter(Statement.event == event_id).order_by(Statement.insertion_time).all() for statement in statements:
elif mode == "past": if statement.speaker in count:
statements = db.session.query(Statement, Speaker).join(Speaker).filter(Statement.executed == True).filter(Statement.event == event_id).order_by(Statement.execution_time).all() count[statement.speaker] += 1
return statements else:
count[statement.speaker] = 1
sorted_speakers = sorted(speakers, key=lambda sp: count[sp.id])
result = []
for speaker in sorted_speakers:
pending_statements = [statement for statement in statements if statement.speaker == speaker.id and not statement.executed]
if len(pending_statements) > 0:
result.append((pending_statements[0], speaker, count[speaker.id]))
return result
if mode == "fifo":
speaker_by_id = { speaker.id: speaker for speaker in speakers }
result = [(statement, speaker_by_id[statement.speaker], 0) for statement in statements if not statement.executed]
return result
print("unknown querying mode {}".format(mode))
@speech.route("/index") @speech.route("/index")
def index(): def index():
mode = request.args.get("mode", "pending")
event_id = request.args.get("event", None) event_id = request.args.get("event", None)
mode = request.args.get("mode", None)
meta = [] meta = []
if event_id is not None and event_id != "-1": if event_id is not None and event_id != "-1":
event = Event.query.filter_by(id=event_id).first() event = Event.query.filter_by(id=event_id).first()
form = AddStatementForm() form = AddStatementForm()
form.event.data = event.id form.event.data = event.id
meta.append((query_statements(mode, event_id), form, event)) meta.append((query_statements(mode if mode is not None else event.mode, event_id), form, event))
else: else:
for event in Event.query.all(): for event in Event.query.all():
form = AddStatementForm() form = AddStatementForm()
form.event.data = event.id form.event.data = event.id
meta.append((query_statements(mode, event.id), form, event)) meta.append((query_statements(mode if mode is not None else event.mode, event.id), form, event))
event_id = -1 event_id = -1
return render_layout("speech_index.html", meta=meta, event_id=event_id) return render_layout("speech_index.html", meta=meta, event_id=event_id, mode=mode)
@speech.route("/show") @speech.route("/show")
def show(): def show():
mode = request.args.get("mode", "pending")
event_id = request.args.get("event", None) event_id = request.args.get("event", None)
mode = request.args.get("mode", None)
meta = [] meta = []
if event_id is not None and event_id is not "-1": if event_id is not None and event_id is not "-1":
event = Event.query.filter_by(id=event_id).first() event = Event.query.filter_by(id=event_id).first()
meta.append((query_statements(mode, event_id), event)) meta.append((query_statements(mode if mode is not None else event.mode, event_id), event))
else: else:
for event in Event.query.all(): for event in Event.query.all():
meta.append((query_statements(mode, event.id), event)) meta.append((query_statements(mode if mode is not None else event.mode, event.id), event))
return render_layout("speech_show.html", mode=mode, meta=meta, event_id=event_id) return render_layout("speech_show.html", mode=mode, meta=meta, event_id=event_id)
@speech.route("/update") @speech.route("/update")
def update(): def update():
mode = request.args.get("mode", "pending")
event_id = request.args.get("event", None) event_id = request.args.get("event", None)
mode = request.args.get("mode", None)
meta = [] meta = []
if event_id is not None and event_id != "-1": if event_id is not None and event_id != "-1":
event = Event.query.filter_by(id=event_id).first() event = Event.query.filter_by(id=event_id).first()
meta.append((query_statements(mode, event_id), event)) meta.append((query_statements(mode if mode is not None else event.mode, event_id), event))
else: else:
for event in Event.query.all(): for event in Event.query.all():
meta.append((query_statements(mode, event.id), event)) meta.append((query_statements(mode if mode is not None else event.mode, event.id), event))
return render_layout("speech_content_show.html", mode=mode, meta=meta) return render_layout("speech_content_show.html", mode=mode, meta=meta)
...@@ -94,7 +105,7 @@ def add(): ...@@ -94,7 +105,7 @@ def add():
statement = Statement(speaker.id, event_id) statement = Statement(speaker.id, event_id)
db.session.add(statement) db.session.add(statement)
db.session.commit() db.session.commit()
mode = request.args.get("mode", "pending") mode = request.args.get("mode", None)
event_id = request.args.get("event", None) event_id = request.args.get("event", None)
return redirect(url_for(request.args.get("next") or ".index", mode=mode, event=event_id)) return redirect(url_for(request.args.get("next") or ".index", mode=mode, event=event_id))
...@@ -111,7 +122,7 @@ def cancel(): ...@@ -111,7 +122,7 @@ def cancel():
db.session.delete(statement) db.session.delete(statement)
db.session.commit() db.session.commit()
flash("Statement canceled", "alert-success") flash("Statement canceled", "alert-success")
mode = request.args.get("mode", "pending") mode = request.args.get("mode", None)
return redirect(url_for(request.args.get("next") or ".index", mode=mode, event=event_id)) return redirect(url_for(request.args.get("next") or ".index", mode=mode, event=event_id))
@speech.route("/done") @speech.route("/done")
...@@ -127,15 +138,15 @@ def done(): ...@@ -127,15 +138,15 @@ def done():
db.session.commit() db.session.commit()
else: else:
flash("Statement already done", "alert-error") flash("Statement already done", "alert-error")
mode = request.args.get("mode", "pending") mode = request.args.get("mode", None)
return redirect(url_for(request.args.get("next") or ".index", mode=mode, event=event_id)) return redirect(url_for(request.args.get("next") or ".index", mode=mode, event=event_id))
@speech.route("/update_show.js") @speech.route("/update_show.js")
def update_show_js(): def update_show_js():
update_interval = config.UPDATE_SHOW_INTERVAL or 1 update_interval = config.UPDATE_SHOW_INTERVAL or 1
div = "rede-content-div" div = "rede-content-div"
mode = request.args.get("mode", "pending") mode = request.args.get("mode", None)
event_id = request.args.get("event", -1) event_id = request.args.get("event", -1)
target_url = url_for(".update", mode=mode, event=event_id) target_url = url_for(".update", mode=mode, event=event_id)
return render_layout("update.js", update_interval=update_interval, div=div, target_url=target_url) return render_layout("update.js", update_interval=update_interval, div=div, target_url=target_url, prefix="update_show_")
...@@ -37,7 +37,7 @@ def index(): ...@@ -37,7 +37,7 @@ def index():
events = Event.query.all() events = Event.query.all()
meta = [] meta = []
for event in events: for event in events:
ls = [ (statement, speaker, count) for (statement, speaker, count) in speech.query_statements("pending", event.id) if not statement.executed ] ls = speech.query_statements(event.mode, event.id)
no_speaker = Speaker("No Speaker", event) no_speaker = Speaker("No Speaker", event)
no_statement = Statement(no_speaker, event) no_statement = Statement(no_speaker, event)
meta.append((ls[0] if len(ls) > 0 else (no_statement, no_speaker, ()), event)) meta.append((ls[0] if len(ls) > 0 else (no_statement, no_speaker, ()), event))
...@@ -48,7 +48,7 @@ def update(): ...@@ -48,7 +48,7 @@ def update():
events = Event.query.all() events = Event.query.all()
meta = [] meta = []
for event in events: for event in events:
ls = [ (statement, speaker, count) for (statement, speaker, count) in speech.query_statements("pending", event.id) if not statement.executed ] ls = speech.query_statements(event.mode, event.id)
no_speaker = Speaker("No Speaker", event) no_speaker = Speaker("No Speaker", event)
no_statement = Statement(no_speaker, event) no_statement = Statement(no_speaker, event)
meta.append((ls[0] if len(ls) > 0 else (no_statement, no_speaker, ()), event)) meta.append((ls[0] if len(ls) > 0 else (no_statement, no_speaker, ()), event))
...@@ -59,7 +59,7 @@ def update_js(): ...@@ -59,7 +59,7 @@ def update_js():
update_interval = config.UPDATE_INDEX_INTERVAL or 1 update_interval = config.UPDATE_INDEX_INTERVAL or 1
div = "rede-content-div" div = "rede-content-div"
target_url = url_for(".update") target_url = url_for(".update")
return render_layout("update.js", update_interval=update_interval, div=div, target=target_url) return render_layout("update.js", update_interval=update_interval, div=div, target_url=target_url, prefix="index_")
@app.route("/update_time") @app.route("/update_time")
def update_time(): def update_time():
...@@ -70,7 +70,7 @@ def update_time_js(): ...@@ -70,7 +70,7 @@ def update_time_js():
update_interval = config.UPDATE_TIME_INTERVAL or 10 update_interval = config.UPDATE_TIME_INTERVAL or 10
div = "rede-time-div" div = "rede-time-div"
target_url = url_for("update_time") target_url = url_for("update_time")
return render_layout("update.js", update_interval=update_interval, div=div, target_url=target_url) return render_layout("update.js", update_interval=update_interval, div=div, target_url=target_url, prefix="time_")
@app.route("/login", methods=["GET", "POST"]) @app.route("/login", methods=["GET", "POST"])
def login(): def login():
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<thead> <thead>
<tr> <tr>
<th class="mdl-data-table__cell--non-numeric">Name</th> <th class="mdl-data-table__cell--non-numeric">Name</th>
<th class="mdl-data-table__cell--non-numeric">Date</th> <th class="mdl-data-table__cell--non-numeric">Mode</th>
<th class="mdl-data-table__cell--non-numeric">Delete</th> <th class="mdl-data-table__cell--non-numeric">Delete</th>
</tr> </tr>
</thead> </thead>
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
{% for event in events %} {% for event in events %}
<tr> <tr>
<td class="mdl-data-table__cell--non-numeric"><a href="{{ url_for(".event_edit", id=event.id) }}">{{ event.name }}</a></td> <td class="mdl-data-table__cell--non-numeric"><a href="{{ url_for(".event_edit", id=event.id) }}">{{ event.name }}</a></td>
<td class="mdl-data-table__cell--non-numeric">{{ event.date.strftime("%d.%m.%Y") }}</td> <td class="mdl-data-table__cell--non-numeric">{{ event.mode }}</td>
<td class="mdl-data-table__cell--non-numeric"> <td class="mdl-data-table__cell--non-numeric">
<a href="{{ url_for('.event_delete', id=event.id) }}"> <a href="{{ url_for('.event_delete', id=event.id) }}">
<i class="material-icons">delete</i> <i class="material-icons">delete</i>
......
...@@ -32,14 +32,14 @@ ...@@ -32,14 +32,14 @@
<thead> <thead>
<tr> <tr>
<th class="mdl-data-table__cell--non-numeric">Name</th> <th class="mdl-data-table__cell--non-numeric">Name</th>
<th class="mdl-data-table__cell--non-numeric">Date</th> <th class="mdl-data-table__cell--non-numeric">Mode</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for event in events %} {% for event in events %}
<tr> <tr>
<td class="mdl-data-table__cell--non-numeric"><a href="{{ url_for(".event_edit", id=event.id) }}">{{ event.name }}</a></td> <td class="mdl-data-table__cell--non-numeric"><a href="{{ url_for(".event_edit", id=event.id) }}">{{ event.name }}</a></td>
<td class="mdl-data-table__cell--non-numeric">{{ event.date.strftime("%d.%m.%Y") }}</td> <td class="mdl-data-table__cell--non-numeric">{{ event.mode }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
......
...@@ -5,27 +5,17 @@ ...@@ -5,27 +5,17 @@
</div> </div>
<div class="mdl-card__actions"> <div class="mdl-card__actions">
{% if current_user.is_authenticated() and "user" in current_user.roles %} {% if current_user.is_authenticated() and "user" in current_user.roles %}
<a href="{{ url_for("speech.index", event=event.id, mode="pending") }}"> <a href="{{ url_for("speech.index", event=event.id) }}">
<button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored"> <button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
<i class="material-icons" role="presentation">build</i> <i class="material-icons" role="presentation">build</i>
</button> </button>
</a> </a>
{% endif %} {% endif %}
<a href="{{ url_for("speech.show", event=event.id, mode="pending") }}"> <a href="{{ url_for("speech.show", event=event.id) }}">
<button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
<i class="material-icons" role="presentation">announcement</i>
</button>
</a>
<a href="{{ url_for("speech.show", event=event.id, mode="all") }}">
<button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored"> <button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
<i class="material-icons" role="presentation">list</i> <i class="material-icons" role="presentation">list</i>
</button> </button>
</a> </a>
<a href="{{ url_for("speech.show", event=event.id, mode="past") }}">
<button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
<i class="material-icons" role="presentation">schedule</i>
</button>
</a>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
...@@ -78,11 +78,9 @@ ...@@ -78,11 +78,9 @@
</header> </header>
<nav class="rede-navigation mdl-navigation mdl-color--blue-grey-800"> <nav class="rede-navigation mdl-navigation mdl-color--blue-grey-800">
{% if current_user.is_authenticated() and "user" in current_user.roles %} {% if current_user.is_authenticated() and "user" in current_user.roles %}
<a class="mdl-navigation__link" href="{{ url_for("speech.index", mode="pending") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">build</i>Handle speakers</a> <a class="mdl-navigation__link" href="{{ url_for("speech.index") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">build</i>Handle speakers</a>
{% endif %} {% endif %}
<a class="mdl-navigation__link" href="{{ url_for("speech.show", mode="pending") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">announcement</i>Pending speakers</a> <a class="mdl-navigation__link" href="{{ url_for("speech.show") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">announcement</i>Pending speakers</a>
<a class="mdl-navigation__link" href="{{ url_for("speech.show", mode="all") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">list</i>All speakers</a>
<a class="mdl-navigation__link" href="{{ url_for("speech.show", mode="past") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">schedule</i>Past speakers</a>
{% if current_user.is_authenticated() and "admin" in current_user.roles %} {% if current_user.is_authenticated() and "admin" in current_user.roles %}
<a class="mdl-navigation__link" href="{{ url_for("admin.index") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">computer</i>Administration</a> <a class="mdl-navigation__link" href="{{ url_for("admin.index") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">computer</i>Administration</a>
{% endif %} {% endif %}
......
...@@ -4,30 +4,9 @@ ...@@ -4,30 +4,9 @@
<thead> <thead>
<tr> <tr>
<th class="mdl-data-table__cell--non-numeric">Speaker for {{ event.name }}</th> <th class="mdl-data-table__cell--non-numeric">Speaker for {{ event.name }}</th>
{% if mode == "all" or mode == "past" %}
<th class="mdl-data-table__cell--non-numeric">Time</th>
{% endif %}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% if mode == "all" or mode == "past" %}
{% for statement, speaker in statements %}
<tr>
<td class="mdl-data-table__cell--non-numeric">
{{ speaker.name }}
</td>
{% if mode == "all" %}
<td class="mdl-data-table__cell--non-numeric">
{{ statement.insertion_time.strftime("%d. %B %Y, %H:%M") }}
</td>
{% elif mode == "past" %}
<td class="mdl-data-table__cell--non-numeric">
{{ statement.execution_time.strftime("%d. %B %Y, %H:%M") }}
</td>
{% endif %}
</tr>
{% endfor %}
{% elif mode == "pending" %}
{% for statement, speaker, count in statements %} {% for statement, speaker, count in statements %}
{% if not statement.executed %} {% if not statement.executed %}
<tr> <tr>
...@@ -37,7 +16,6 @@ ...@@ -37,7 +16,6 @@
</tr> </tr>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% endif %}
</tbody> </tbody>
</table> </table>
{% endfor %} {% endfor %}
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
<thead> <thead>
<tr> <tr>
<th class="mdl-data-table__cell--non-numeric">Speaker</th> <th class="mdl-data-table__cell--non-numeric">Speaker</th>
{% if (mode is not none and mode == "balanced") or (mode is none and event.mode == "balanced") %}
<th>Count</th> <th>Count</th>
{% endif %}
{% if "user" in current_user.roles %} {% if "user" in current_user.roles %}
<th class="mdl-data-table__cell--non-numeric">Done</th> <th class="mdl-data-table__cell--non-numeric">Done</th>
<th class="mdl-data-table__cell--non-numeric">Cancel</th> <th class="mdl-data-table__cell--non-numeric">Cancel</th>
...@@ -17,14 +19,15 @@ ...@@ -17,14 +19,15 @@
</thead> </thead>
<tbody> <tbody>
{% for statement, speaker, count in statements %} {% for statement, speaker, count in statements %}
{% if not statement.executed %}
<tr> <tr>
<td class="mdl-data-table__cell--non-numeric"> <td class="mdl-data-table__cell--non-numeric">
<h5>{{ speaker.name }}</h5> <h5>{{ speaker.name }}</h5>
</td> </td>
{% if (mode is not none and mode == "balanced") or (mode is none and event.mode == "balanced") %}
<td> <td>
<h5>{{ count }}</h5> <h5>{{ count }}</h5>
</td> </td>
{% endif %}
{% if "user" in current_user.roles %} {% if "user" in current_user.roles %}
<td class="mdl-data-table__cell--non-numeric"> <td class="mdl-data-table__cell--non-numeric">
<a href="{{ url_for(".done", statement=statement.id, next=".index", event=event_id) }}"> <a href="{{ url_for(".done", statement=statement.id, next=".index", event=event_id) }}">
...@@ -42,7 +45,6 @@ ...@@ -42,7 +45,6 @@
</td> </td>
{% endif %} {% endif %}
</tr> </tr>
{% endif %}
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
......
var returned = true; var {{ prefix }}returned = true;
var last_content = ""; var {{ prefix }}last_content = "";
function request() { function {{ prefix }}request() {
if (!returned) if (!{{ prefix }}returned)
return; return;
returned = false; {{ prefix }}returned = false;
var xmlhttp = new XMLHttpRequest(); var {{ prefix }}xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange=function() { {{ prefix }}xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if ({{ prefix }}xmlhttp.readyState == 4 && {{ prefix }}xmlhttp.status == 200) {
returned = true; {{ prefix }}returned = true;
update(xmlhttp.responseText); {{ prefix }}update({{ prefix }}xmlhttp.responseText);
} }
}; };
var target = "{{ target_url }}"; var {{ prefix }}target = "{{ target_url }}";
xmlhttp.open("GET", target, true); {{ prefix }}xmlhttp.open("GET", {{ prefix }}target, true);
xmlhttp.send(); {{ prefix }}xmlhttp.send();
} }
function update(data) { function {{ prefix }}update({{ prefix }}data) {
if (data != last_content) { if ({{ prefix }}data != {{ prefix }}last_content) {
document.getElementById("{{ div }}").innerHTML = data; document.getElementById("{{ div }}").innerHTML = {{ prefix }}data;
last_content = data; {{ prefix }}last_content = {{ prefix }}data;
} }
} }
var {{ prefix }}f = window.onload;
window.onload=function() { window.onload=function() {
window.setInterval(request, 1000 * {{ update_interval }}); {{ prefix }}f();
window.setInterval({{ prefix }}request, 1000 * {{ update_interval }});
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment