Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into 30-m03-implement-pati…
Browse files Browse the repository at this point in the history
…ent-phase-change
  • Loading branch information
claasga committed Mar 28, 2024
2 parents 408044b + 96670a5 commit 7379ac0
Show file tree
Hide file tree
Showing 33 changed files with 673 additions and 275 deletions.
1 change: 1 addition & 0 deletions backend/dps_training_k/configuration/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
]

MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
Expand Down
35 changes: 12 additions & 23 deletions backend/dps_training_k/game/consumers/abstract_consumer.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class ClosureCodes:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.exercise_code = ""
self.exercise = None
self.REQUESTS_MAP = {}
self.user = None

Expand Down Expand Up @@ -141,51 +142,39 @@ def disconnect(self, code):
# self.user.clear_channel_name()
code = self.ClosureCodes.UNKNOWN if not code else code
super().disconnect(code)

def authenticate(self, token):
try:
token = Token.objects.get(key=token)
self.user = token.user
self.user.set_channel_name(self.channel_name)
return True
return True, self.user.username
except Token.DoesNotExist:
self.close(code=self.ClosureCodes.NOT_AUTHENTICATED)
return False
return False, None

def _send_exercise(self):
exercise = Exercise.createExercise()
patient = Patient.objects.create(
name="Max Mustermann", exercise=exercise, patientId=123456
name="Max Mustermann", exercise=self.exercise, patientId=123456
)
exercise_object = {
"exercise": {
"exerciseId": exercise.exerciseId,
"exerciseId": self.exercise.exerciseId,
"areas": [
{
"areaName": "X",
"patients": [
{
"patientId": patient.patientId,
"patientName": patient.name,
"patientCode": 0
}
],
"personnel": [
{
"personnelId": 0,
"personnelName": "X"
"patientCode": 0,
"triage": patient.triage,
}
],
"material": [
{
"materialId": 0,
"materialName": "X"
}
]
"personnel": [{"personnelId": 0, "personnelName": "X"}],
"material": [{"materialId": 0, "materialName": "X"}],
}
]
],
}
}
self.send_event(
self.OutgoingMessageTypes.EXERCISE, exercise=exercise_object
)
self.send_event(self.OutgoingMessageTypes.EXERCISE, exercise=exercise_object)
23 changes: 19 additions & 4 deletions backend/dps_training_k/game/consumers/patient_consumer.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from .abstract_consumer import AbstractConsumer
from urllib.parse import parse_qs
from game.models import Patient


class PatientConsumer(AbstractConsumer):
class PatientIncomingMessageTypes:
EXAMPLE = "example"
TEST_PASSTHROUGH = "test-passthrough"
TRIAGE = "triage"

class PatientOutgoingMessageTypes:
RESPONSE = "response"
Expand All @@ -14,7 +16,8 @@ class PatientOutgoingMessageTypes:

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.patient_code = ""
self.patientId = ""
self.patient = None
self.REQUESTS_MAP = {
self.PatientIncomingMessageTypes.EXAMPLE: (
self.handle_example,
Expand All @@ -24,25 +27,37 @@ def __init__(self, *args, **kwargs):
self.PatientIncomingMessageTypes.TEST_PASSTHROUGH: (
self.handle_test_passthrough,
),
self.PatientIncomingMessageTypes.TRIAGE: (
self.handle_triage,
"triage",
),
}

def connect(self):
query_string = parse_qs(self.scope["query_string"].decode())
token = query_string.get("token", [None])[0]
if self.authenticate(token):
success, patientId = self.authenticate(token)
if success:
self.patient = Patient.objects.get(patientId=patientId)
self.patientId = patientId
self.exercise = self.patient.exercise
self.accept()
self._send_exercise()

def handle_example(self, exercise_code, patient_code):
self.exercise_code = exercise_code
self.patient_code = patient_code
self.patientId = patient_code
self.send_event(
self.PatientOutgoingMessageTypes.RESPONSE,
content=f"exercise_code {self.exercise_code} & patient_code {self.patient_code}",
content=f"exercise_code {self.exercise_code} & patient_code {self.patientId}",
)

def handle_test_passthrough(self):
self.send_event(
self.PatientOutgoingMessageTypes.TEST_PASSTHROUGH,
message="received test event",
)

def handle_triage(self, triage):
self.patient.triage = triage
self._send_exercise()
2 changes: 2 additions & 0 deletions backend/dps_training_k/game/consumers/trainer_consumer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .abstract_consumer import AbstractConsumer
from game.models import Exercise


class TrainerConsumer(AbstractConsumer):
Expand Down Expand Up @@ -59,6 +60,7 @@ def handle_example(self, exercise_code):
)

def handle_create_exercise(self):
self.exercise = Exercise.createExercise()
self._send_exercise()

def handle_test_passthrough(self):
Expand Down
18 changes: 18 additions & 0 deletions backend/dps_training_k/game/migrations/0006_patient_triage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0.1 on 2024-03-25 14:08

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('game', '0005_rename_invitation_code_exercise_exerciseid_and_more'),
]

operations = [
migrations.AddField(
model_name='patient',
name='triage',
field=models.CharField(choices=[('-', 'undefined'), ('R', 'red'), ('Y', 'yellow'), ('G', 'green'), ('A', 'airway'), ('B', 'breathing'), ('C', 'circulation'), ('D', 'disability'), ('E', 'exposure')], default='-'),
),
]
15 changes: 15 additions & 0 deletions backend/dps_training_k/game/models/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@


class Patient(Eventable, Transitionable, UpdateSignals, models.Model):
class Triage(models.TextChoices):
UNDEFINED = "-", "undefined"
RED = "R", "red"
YELLOW = "Y", "yellow"
GREEN = "G", "green"
Airway = "A", "airway"
BREATHING = "B", "breathing"
CIRCULATION = "C", "circulation"
DISABILITY = "D", "disability"
EXPOSURE = "E", "exposure"

name = models.CharField(
max_length=100, default="Max Mustermann"
) # technically patientData but kept here for simplicity for now
Expand All @@ -24,6 +35,10 @@ class Patient(Eventable, Transitionable, UpdateSignals, models.Model):
patientId = models.IntegerField(
help_text="patientId used to log into patient - therefore part of authentication"
)
triage = models.CharField(
choices=Triage.choices,
default=Triage.UNDEFINED,
)

def __str__(self):
return f"Patient #{self.id} called {self.name} with ID {self.patientId}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class Meta:
class ExerciseFactory(factory.django.DjangoModelFactory):
class Meta:
model = Exercise
django_get_or_create = ("config", "invitation_code", "state")
django_get_or_create = ("config", "exerciseId", "state")

config = factory.SubFactory(SavedExerciseFactory)
invitation_code = "a" * settings.INVITATION_LOGIC.code_length
exerciseId = "a" * settings.INVITATION_LOGIC.code_length
state = Exercise.ExerciseStateTypes.CONFIGURATION
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
class PatientFactory(factory.django.DjangoModelFactory):
class Meta:
model = Patient
django_get_or_create = ("name", "exercise", "patientCode")
django_get_or_create = ("name", "exercise", "patientId")

name = "Max Mustermann"
exercise = factory.SubFactory(ExerciseFactory)
patientCode = 123456
patientId = 123456
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.test import TransactionTestCase
from game.models import User
from .factories import PatientFactory
from rest_framework.authtoken.models import Token
from configuration.asgi import application
from channels.testing import WebsocketCommunicator
Expand All @@ -9,8 +10,9 @@ class PatientWebSocketTest(TransactionTestCase):
def setUp(self):
super().setUp()
# Create a user and token for testing
self.user = User.objects.create_user(username="testpatient123", password="test")
self.user = User.objects.create_user(username="123456", password="test")
self.token, _ = Token.objects.get_or_create(user=self.user)
self.patient = PatientFactory()

async def test_authenticated_websocket_connection(self):
# Connect to the WebSocket
Expand Down
14 changes: 11 additions & 3 deletions backend/dps_training_k/game/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,26 @@
from rest_framework.response import Response
from django.contrib.auth import authenticate
from rest_framework.authtoken.models import Token
from game.models import User


class PatientAccessView(APIView):
def post(self, request, *args, **kwargs):
user, created = User.objects.get_or_create(
username="123456"
) # Ensure the username is a string
if created:
user.set_password("2") # Properly hash the password
user.save()

if not (request.data.get("exerciseId") and request.data.get("patientId")):
return Response(
status=status.HTTP_400_BAD_REQUEST,
data="Some required fields are missing",
)
exercise_code = request.data.get("exerciseId")
patient_code = request.data.get("patientId")
user = authenticate(username=exercise_code, password=patient_code)
exercise_id = str(request.data.get("exerciseId"))
patient_id = str(request.data.get("patientId"))
user = authenticate(username=exercise_id, password=patient_id)
if user:
token, created = Token.objects.get_or_create(user=user)
return Response({"token": token.key}, status=status.HTTP_200_OK)
Expand Down
60 changes: 60 additions & 0 deletions frontend/src/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,63 @@ button:active {
background-color: var(--green);
}

.popup-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
text-align: center;
z-index: 1;
}

.list {
margin-top: 30px;
margin-left: 30px;
margin-right: 30px;
}

.listItem {
position: relative;
background-color: #FFFFFF;
border: 1px solid rgb(209, 213, 219);
display: flex;
align-items: center;
text-align: left;
margin-top: -1px;
}

.listItemButton {
position: relative;
background-color: #FFFFFF;
border: none;
display: flex;
align-items: center;
font-size: 1.25rem;
padding: .75rem 1rem;
padding-left: 0;
text-align: left;
height: 50px;
width: 100%;
}

.listItemAddButton {
text-align: center;
position: relative;
background-color: #FFFFFF;
border: 1px solid rgb(209, 213, 219);
box-sizing: border-box;
width: 100%;
font-size: 1.25rem;
line-height: 1.25rem;
padding: .75rem 1rem;
margin-top: -1px;
}

.listItemId, .listItemName {
padding: .75rem 1rem;
}
Loading

0 comments on commit 7379ac0

Please sign in to comment.