Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement 'Sense of Place' and Character Interactions #18

Open
10 tasks
brylie opened this issue Aug 18, 2024 · 0 comments
Open
10 tasks

Implement 'Sense of Place' and Character Interactions #18

brylie opened this issue Aug 18, 2024 · 0 comments
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed

Comments

@brylie
Copy link
Owner

brylie commented Aug 18, 2024

We want to enhance our language learning app by introducing a more immersive, game-like experience. This feature will create a "sense of place" by defining locations, characters, and a progression system for lessons. The goal is to make the learning experience more engaging, personalized, and situated within a coherent virtual world.

Key Features

  1. Locations: Pre-defined places where lessons occur (e.g., "Claire's Coffee Shop")
  2. Characters: Individuals associated with locations, with persistent memory of player interactions
  3. Lesson Progression: A sequence of lessons tied to each location, increasing in complexity
  4. Player Memory: Tracking of completed lessons and character interactions

Why

  1. Engagement: Creates a more immersive and compelling learning experience
  2. Contextualized Learning: Situates language practice in specific, relatable contexts
  3. Personalization: Builds a sense of familiarity and progression for the user
  4. Flexible Content Creation: Allows for structured, themed lesson creation by teachers/content creators

Implementation Ideas

1. New Data Models

Add the following models to app/lessons/models.py:

from django.db import models
from django.contrib.auth import get_user_model
from wagtail.models import Page
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel

User = get_user_model()

class Location(models.Model):
    title = models.CharField(max_length=100)
    description = RichTextField()
    image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    panels = [
        FieldPanel('title'),
        FieldPanel('description'),
        FieldPanel('image'),
    ]

    def __str__(self):
        return self.title

class Character(models.Model):
    name = models.CharField(max_length=100)
    occupation = models.CharField(max_length=100)
    background = RichTextField()
    image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    panels = [
        FieldPanel('name'),
        FieldPanel('occupation'),
        FieldPanel('background'),
        FieldPanel('image'),
    ]

    def __str__(self):
        return self.name

class CharacterKnowledge(models.Model):
    character = models.ForeignKey(Character, on_delete=models.CASCADE, related_name='knowledge')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    summary = models.TextField()
    last_updated = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ['character', 'user']

    def __str__(self):
        return f"{self.character.name}'s knowledge about {self.user.username}"

class LessonCompletion(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    lesson = models.ForeignKey('Lesson', on_delete=models.CASCADE)
    status = models.CharField(max_length=20, choices=[('attempted', 'Attempted'), ('completed', 'Completed')])
    completed_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ['user', 'lesson']

    def __str__(self):
        return f"{self.user.username} - {self.lesson.title} ({self.status})"

2. Update Lesson Model

Modify the Lesson model in app/lessons/models.py:

class Lesson(Page):
    # ... existing fields ...
    location = models.ForeignKey(Location, on_delete=models.SET_NULL, null=True, related_name='lessons')
    character = models.ForeignKey(Character, on_delete=models.SET_NULL, null=True, related_name='lessons')
    sequence_number = models.PositiveIntegerField(help_text="The order of this lesson within its location")

    content_panels = Page.content_panels + [
        # ... existing panels ...
        FieldPanel('location'),
        FieldPanel('character'),
        FieldPanel('sequence_number'),
    ]

    def get_character_knowledge(self, user):
        knowledge, created = CharacterKnowledge.objects.get_or_create(
            character=self.character,
            user=user,
            defaults={'summary': ''}
        )
        return knowledge

    def update_character_knowledge(self, user, transcript):
        knowledge = self.get_character_knowledge(user)
        # Use LLM to update knowledge based on transcript and previous summary
        updated_summary = self.generate_updated_summary(knowledge.summary, transcript)
        knowledge.summary = updated_summary
        knowledge.save()

    def generate_updated_summary(self, previous_summary, transcript):
        # Implement LLM call here to generate updated summary
        # This is a placeholder and needs to be implemented
        return "Updated summary based on interaction"

    def mark_completion(self, user, status='completed'):
        LessonCompletion.objects.update_or_create(
            user=user,
            lesson=self,
            defaults={'status': status}
        )

    def serve(self, request):
        # ... existing serve logic ...

        if request.method == 'POST':
            # ... existing POST logic ...
            
            # After conversation is complete
            transcript = Transcript.objects.get(id=request.session.get('transcript_id'))
            self.update_character_knowledge(request.user, transcript)
            self.mark_completion(request.user)

        # ... rest of the serve method ...

3. Update Admin Interface

Create a new file app/lessons/viewsets.py:

from wagtail.admin.viewsets.model import ModelViewSet
from .models import Location, Character

class LocationViewSet(ModelViewSet):
    model = Location
    menu_label = 'Locations'
    menu_icon = 'site'
    menu_order = 200
    add_to_settings_menu = False
    exclude_from_explorer = False
    list_display = ('title', 'description')
    search_fields = ('title', 'description')

class CharacterViewSet(ModelViewSet):
    model = Character
    menu_label = 'Characters'
    menu_icon = 'user'
    menu_order = 201
    add_to_settings_menu = False
    exclude_from_explorer = False
    list_display = ('name', 'occupation')
    search_fields = ('name', 'occupation', 'background')

# Register the viewsets
location_viewset = LocationViewSet('locations')
character_viewset = CharacterViewSet('characters')

Then, update app/lessons/wagtail_hooks.py:

from wagtail import hooks
from .viewsets import location_viewset, character_viewset

@hooks.register('register_admin_viewset')
def register_viewsets():
    return [
        location_viewset,
        character_viewset,
    ]

This approach using ModelViewSet provides more flexibility and is the recommended way to create admin interfaces in Wagtail 6 and later. It allows for easy customization of each model's views, forms, and permissions.

4. Update Templates

Modify app/lessons/templates/lessons/lesson.html to include location and character information:

{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}

{% block content %}
<div class="location-info">
    <h2>{{ page.location.title }}</h2>
    {% image page.location.image fill-300x200 as location_img %}
    <img src="{{ location_img.url }}" alt="{{ page.location.title }}">
    {{ page.location.description|richtext }}
</div>

<div class="character-info">
    <h3>{{ page.character.name }} - {{ page.character.occupation }}</h3>
    {% image page.character.image fill-150x150 as character_img %}
    <img src="{{ character_img.url }}" alt="{{ page.character.name }}">
    {{ page.character.background|richtext }}
</div>

<!-- ... existing lesson content ... -->
{% endblock %}

Additional Considerations

  1. Performance: Optimize database queries, especially for character knowledge retrieval and updates.
  2. Content Creation: Develop tools or guidelines for content creators to easily create themed lesson sequences.
  3. User Experience: Design an intuitive interface for users to navigate between locations and lessons.
  4. Scalability: Plan for potential expansion of locations, characters, and lesson complexity.
  5. LLM Integration: Implement robust error handling and rate limiting for LLM calls in character knowledge updates.

Acceptance Criteria

  1. New models (Location, Character, CharacterKnowledge, LessonCompletion) are created and working correctly.
  2. Lessons are associated with locations and characters, and can be created/edited in the Wagtail admin.
  3. LLM updates Character knowledge after each lesson.
  4. Lesson completion status is tracked for each user.
  5. Lesson pages display relevant location and character information.
  6. Locations and Characters can be managed through the Wagtail admin interface.
  7. The system maintains a coherent progression of lessons within each location.
  8. Performance impact of new features is minimal and acceptable.
  9. Appropriate unit tests are written for new models and methods.
  10. The code follows our project's style guide and best practices.

Future Enhancements

  • Implement a "world map" interface for users to navigate between locations.
  • Add quests or objectives that span multiple locations and characters.
  • Introduce mini-games or puzzles specific to each location.
  • Implement a reward system for completing location-based lesson sequences.

Resources

@brylie brylie added enhancement New feature or request help wanted Extra attention is needed good first issue Good for newcomers labels Aug 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

1 participant