Skip to content

Commit

Permalink
add save/load of the game state, make the router "cheat-proof"
Browse files Browse the repository at this point in the history
  • Loading branch information
astynax committed Feb 10, 2021
1 parent 7593975 commit 4d6e02f
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 27 deletions.
23 changes: 23 additions & 0 deletions djaif/book/migrations/0012_progresssave.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.0.5 on 2021-02-10 17:01

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('book', '0011_auto_20200526_1529'),
]

operations = [
migrations.CreateModel(
name='ProgressSave',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('book_page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='book.BookPage')),
('items', models.ManyToManyField(blank=True, to='book.Item')),
('progress', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='book.BookProgress')),
],
),
]
18 changes: 18 additions & 0 deletions djaif/book/migrations/0013_progresssave_updated_at.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.0.5 on 2021-02-10 17:05

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('book', '0012_progresssave'),
]

operations = [
migrations.AddField(
model_name='progresssave',
name='updated_at',
field=models.DateTimeField(auto_now=True),
),
]
29 changes: 29 additions & 0 deletions djaif/book/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,35 @@ def start_reading(cls, user, book):
progress.save()
return progress

def save_to(self, save_id):
if save_id is None:
state = ProgressSave.objects.create(
progress=self,
book_page=self.book_page,
)
state.items.set(self.items.all())
else:
state = ProgressSave.objects.get(id=save_id)
state.book_page=self.book_page
state.save()
state.items.set(self.items.all())

def load_from(self, save_id):
state = ProgressSave.objects.get(id=save_id)
self.book_page=state.book_page
self.save()
self.items.set(state.items.all())


class ProgressSave(models.Model):
progress = models.ForeignKey(BookProgress, on_delete=models.CASCADE)

updated_at = models.DateTimeField(auto_now=True)

book_page = models.ForeignKey(BookPage, on_delete=models.CASCADE)

items = models.ManyToManyField('book.Item', blank=True) # noqa: WPS110


class Item(models.Model):
name = models.TextField()
Expand Down
6 changes: 4 additions & 2 deletions djaif/book/templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ <h3>Вы видите</h3>
<ul>
{% for item in page_items %}
<li>
<a href="{% url 'take' page.book.id page.id item.id %}">
<a href="{% url 'take' page.book.id item.id %}">
{{ item.name }}
</a>
</li>
Expand All @@ -26,7 +26,7 @@ <h3>Куда податься?</h3>
{% for link, passable in links %}
<li>
{% if passable %}
<a href="{% url 'page' page.book.id link.to_page.id %}">
<a href="{% url 'go_to' page.book.id link.id %}">
{{ link.name }}
</a>
{% else %}
Expand All @@ -45,5 +45,7 @@ <h3>Инвентарь</h3>
{% endfor %}
</ul>
{% endif %}
<hr />
<a href="{% url 'saves' page.book.id %}">Сохранения</a>
</body>
</html>
28 changes: 28 additions & 0 deletions djaif/book/templates/saves.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{ book.title }}: Сохранения</title>
</head>
<body>
<h1>
{{ book.title }}
</h1>
<h2>
{{ page.title }}
</h2>
<a href="{% url 'book' book.id %}">[Продолжить игру]</a>
<br/>
<a href="{% url 'save_new' book.id %}">[Новое сохранение]</a>
<ul>
{% for save in saves %}
<li>
<a href="{% url 'delete_save' book.id save.id %}">[Удалить]</a>
<a href="{% url 'load_from' book.id save.id %}">[Загрузить]</a>
<a href="{% url 'save_to' book.id save.id %}">[Заменить]</a>
[{{ save.updated_at|date:"Y.m.d H:i:s" }}] {{ save.book_page.title }}
</li>
{% endfor %}
</ul>
</body>
</html>
25 changes: 21 additions & 4 deletions djaif/book/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,28 @@
urlpatterns = [
path('', views.view_books),
path('book/<int:book_id>', views.view_book, name='book'),
path('book/<int:book_id>/page/<int:page_id>', views.view_page, name='page'),
path('book/<int:book_id>/go/<int:pagelink_id>', views.go_to, name='go_to'),
path('book/<int:book_id>/take/<int:item_id>', views.take, name='take'),
path('book/<int:book_id>/saves', views.view_saves, name='saves'),
path(
'book/<int:book_id>/page/<int:page_id>/take/<int:item_id>',
views.take_item,
name='take',
'book/<int:book_id>/saves/new',
views.save_to,
name='save_new',
),
path(
'book/<int:book_id>/saves/save_to/<int:save_id>',
views.save_to,
name='save_to',
),
path(
'book/<int:book_id>/saves/load_from/<int:save_id>',
views.load_from,
name='load_from',
),
path(
'book/<int:book_id>/saves/delete/<int:save_id>',
views.delete_save,
name='delete_save',
),
path('book/<int:book_id>/map.svg', views.view_book_map),
]
75 changes: 54 additions & 21 deletions djaif/book/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
from djaif.book import models


def _return_to(book_id):
return redirect(reverse('book', kwargs={'book_id': book_id}))


def on_progress(view):
@wraps(view) # noqa: WPS430
def inner(request, book_id, **kwargs):
Expand All @@ -32,33 +36,19 @@ def view_books(request):
context={'books': models.Book.objects.all()},
)


def view_book(request, book_id):
book = get_object_or_404(models.Book, id=book_id)
if not book.first_page:
return render(request, 'book.html', context={'book': book})
assert book.first_page
try:
progress = models.BookProgress.objects.get(
book=book, user=request.user,
)
except models.BookProgress.DoesNotExist:
progress = models.BookProgress.start_reading(
user=request.user, book=book,
book=book, user=request.user,
)
return redirect(
reverse(
'page',
kwargs={'book_id': book.id, 'page_id': progress.book_page.id},
),
)


@on_progress
def view_page(request, progress, book_id, page_id):
page = get_object_or_404(models.BookPage, book__id=book_id, id=page_id)

progress.book_page = page
progress.save()
page = progress.book_page

links = [
(link, link.has_all_needed(list(progress.items.all())))
Expand All @@ -78,16 +68,59 @@ def view_page(request, progress, book_id, page_id):


@on_progress
def take_item(request, progress, book_id, page_id, item_id):
def go_to(request, progress, book_id, pagelink_id):
link = get_object_or_404(models.PageLink, id=pagelink_id)
if (
link.from_page.id == progress.book_page.id
and
link.has_all_needed(progress.items.all())
):
progress.book_page = link.to_page
progress.save()
return _return_to(book_id)


@on_progress
def take(request, progress, book_id, item_id):
item = get_object_or_404(models.Item, id=item_id) # noqa: WPS110

progress.items.add(item)
if item in progress.book_page.items.all():
progress.items.add(item)

return _return_to(book_id)


return redirect(
reverse('page', kwargs={'book_id': book_id, 'page_id': page_id}),
@on_progress
def view_saves(request, progress, book_id):
saves = progress.progresssave_set.order_by('-updated_at').all()
return render(
request,
'saves.html',
context={
'book': progress.book,
'page': progress.book_page,
'saves': saves,
},
)


@on_progress
def save_to(request, progress, book_id, save_id=None):
progress.save_to(save_id)
return redirect(reverse('saves', kwargs={'book_id': book_id}))


@on_progress
def load_from(request, progress, book_id, save_id):
progress.load_from(save_id)
return _return_to(book_id)


def delete_save(request, book_id, save_id):
models.ProgressSave.objects.get(id=save_id).delete()
return redirect(reverse('saves', kwargs={'book_id': book_id}))


def view_book_map(request, book_id):
book = get_object_or_404(models.Book, id=book_id)

Expand Down

0 comments on commit 4d6e02f

Please sign in to comment.