added game state base logic, minor changes

This commit is contained in:
Alexander Karpov 2022-07-02 00:05:05 +03:00
parent df3685b8fe
commit 73db40a4f7
8 changed files with 100 additions and 68 deletions

View File

@ -24,6 +24,11 @@ INSTALLED_APPS = [
"room",
]
if DEBUG:
INSTALLED_APPS.append("django.contrib.staticfiles")
INSTALLED_APPS.append("drf_yasg")
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",

View File

@ -1,9 +1,46 @@
from django.conf import settings
from django.conf.urls.static import static
from django.urls import path, include
from django.template.defaulttags import url
from django.urls import path, include, re_path
urlpatterns = (
[path("api/", include("game.urls"))]
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
# openapi schema
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="Snippets API",
default_version="v1",
description="Test description",
terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="contact@snippets.local"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=(permissions.AllowAny,),
)
urlpatterns = [path("api/", include("game.urls"))] + static(
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT
)
if settings.DEBUG:
urlpatterns += [
re_path(
r"^swagger(?P<format>\.json|\.yaml)$",
schema_view.without_ui(cache_timeout=0),
name="schema-json",
),
re_path(
r"^swagger/$",
schema_view.with_ui("swagger", cache_timeout=0),
name="schema-swagger-ui",
),
re_path(
r"^redoc/$",
schema_view.with_ui("redoc", cache_timeout=0),
name="schema-redoc",
),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View File

@ -11,4 +11,4 @@ def generate_charset(length: int):
def gen_ton():
return "".join([str(randint(0, 9)) for _ in range(48)])
return int("".join([str(randint(0, 9)) for _ in range(48)]))

View File

@ -1,7 +1,6 @@
import random
import uuid
from django.core.files import File
from django.core.validators import (
MinValueValidator,
MaxValueValidator,
@ -9,18 +8,16 @@ from django.core.validators import (
MaxLengthValidator,
)
from django.db import models
from django.conf import settings
from common.generators import generate_charset
from game.services.jwt import sign_jwt
HER0_TYPES = [
("WIZARD", "wizard"),
("ARCHER", "archer"),
("WARRIOR", "warrior"),
("KING", "king"),
]
HER0_IMAGE_TYPES = [("DIE", "die"), ("IDLE", "idle"), ("ATTACK", "attack")]
class HeroTypes(models.TextChoices):
wizard = "WIZARD", "wizard"
archer = "ARCHER", "archer"
warrior = "WARRIOR", "warrior"
king = "KING", "king"
class Player(models.Model):
@ -47,7 +44,7 @@ class Player(models.Model):
+ ["ARCHER" for _ in range(4)]
+ ["WARRIOR" for _ in range(6)]
+ ["WIZARD" for _ in range(2)]
+ [random.choice(HER0_TYPES[:3])[0] for _ in range(3)]
+ [random.choice(HeroTypes.choices[:3])[0] for _ in range(3)]
)
for t in types:
hero = Hero()
@ -99,16 +96,8 @@ class Hero(models.Model):
)
added = models.DateTimeField(auto_now_add=True)
type = models.CharField(blank=False, choices=HER0_TYPES, max_length=7)
idle_img_f = models.ForeignKey(
"HeroImageSet", on_delete=models.CASCADE, related_name="idle_image_fkey"
)
attack_img_f = models.ForeignKey(
"HeroImageSet", on_delete=models.CASCADE, related_name="attack_image_fkey"
)
die_img_f = models.ForeignKey(
"HeroImageSet", on_delete=models.CASCADE, related_name="die_image_fkey"
)
type = models.CharField(blank=False, choices=HeroTypes.choices, max_length=7)
model = models.ForeignKey("HeroModelSet", on_delete=models.CASCADE)
health = models.IntegerField(
validators=[MinValueValidator(1), MaxValueValidator(10)], blank=False
)
@ -135,13 +124,13 @@ class Hero(models.Model):
self, force_insert=False, force_update=False, using=None, update_fields=None
):
self.idle_img_f = random.choice(
[x for x in HeroImageSet.objects.filter(hero_type=self.type, type="IDLE")]
[x for x in HeroModelSet.objects.filter(hero_type=self.type)]
)
self.attack_img_f = random.choice(
[x for x in HeroImageSet.objects.filter(hero_type=self.type, type="ATTACK")]
[x for x in HeroModelSet.objects.filter(hero_type=self.type)]
)
self.die_img_f = random.choice(
[x for x in HeroImageSet.objects.filter(hero_type=self.type, type="DIE")]
[x for x in HeroModelSet.objects.filter(hero_type=self.type)]
)
super(Hero, self).save()
@ -154,13 +143,12 @@ class Hero(models.Model):
verbose_name_plural = "heroes"
class HeroImageSet(models.Model):
type = models.CharField(max_length=10, choices=HER0_IMAGE_TYPES)
hero_type = models.CharField(blank=False, choices=HER0_TYPES, max_length=7)
image = models.ImageField(upload_to="uploads/")
class HeroModelSet(models.Model):
hero_type = models.CharField(blank=False, choices=HeroTypes.choices, max_length=7)
model = models.ImageField(upload_to="uploads/")
def __str__(self):
return f"{self.hero_type} {self.type} image"
return f"{self.hero_type} model file"
class Deck(models.Model):

View File

@ -5,7 +5,7 @@ from channels.generic.websocket import AsyncWebsocketConsumer
from channels.layers import get_channel_layer
from game.models import Deck
from room.models import PlayerInQueue, Room, PlayerInRoom
from room.models import PlayerInQueue, Room, PlayerInRoom, GameState
from room.services.room_create import create_room
channel_layer = get_channel_layer()
@ -208,15 +208,18 @@ class RoomConsumer(AsyncWebsocketConsumer):
if not await self.connect_to_room():
await self.close()
else:
message, round = await self.get_state()
await self.send(
json.dumps(
{
"type": "INFO",
"message": f"welcome to room {self.room_name}",
"opponent_score": self.scope["opponent_score"],
"opponent_deck": self.scope["opponent_deck"],
"opponent_online": self.scope["opponent_online"],
"first": self.scope["first"],
"state": message,
"round": round,
},
)
)
@ -236,6 +239,11 @@ class RoomConsumer(AsyncWebsocketConsumer):
# Join room group
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
@sync_to_async
def get_state(self):
state = self.scope["player_in_room"].get_state()
return state.message, state.round
@sync_to_async
def connect_to_room(self):
slug = self.scope["url_route"]["kwargs"]["room_name"]
@ -346,6 +354,12 @@ class RoomConsumer(AsyncWebsocketConsumer):
if "first" in event:
msg["first"] = event["first"]
if "state" in event:
msg["state"] = event["state"]
if "round" in event:
msg["round"] = event["round"]
await self.send(text_data=json.dumps(msg))
# Receive message from room group

View File

@ -9,38 +9,7 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('game', '0002_deck_heroimageset_heroindeck_playerauthsession_and_more'),
]
operations = [
migrations.CreateModel(
name='Room',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.SlugField(max_length=16, unique=True)),
('created', models.DateTimeField(auto_now_add=True)),
('ended', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='PlayerInRoom',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('first', models.BooleanField()),
('score', models.IntegerField()),
('deck', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='decks', to='game.deck')),
('player', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='game.player')),
('room', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='players', to='room.room')),
],
),
migrations.CreateModel(
name='PlayerInQueue',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('channel_name', models.CharField(max_length=50)),
('score', models.IntegerField()),
('deck', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='game.deck')),
('player', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='game.player')),
],
),
]

View File

@ -33,5 +33,18 @@ class PlayerInRoom(models.Model):
online = models.BooleanField(default=False)
channel_name = models.CharField(max_length=50, blank=True, null=True)
def get_state(self):
return GameState.objects.filter(player=self.player, room=self.room).last()
def __str__(self):
return f"{self.player.name} in room {self.room.slug}"
class GameState(models.Model):
room = models.ForeignKey(Room, on_delete=models.CASCADE)
player = models.ForeignKey(Player, on_delete=models.CASCADE)
round = models.IntegerField(blank=False)
message = models.CharField(max_length=100, blank=False)
class Meta:
unique_together = ["room", "player", "round"]

View File

@ -3,7 +3,7 @@ from random import randint
from common.generators import generate_charset
from game.models import Player
from room.models import Room, PlayerInRoom
from room.models import Room, PlayerInRoom, GameState
@sync_to_async
@ -36,4 +36,10 @@ def create_room(
deck_id=deck_id_2,
first=first_player == 2,
)
GameState.objects.create(
room=room, player=player_1, round=0, message="Game started"
)
GameState.objects.create(
room=room, player=player_2, round=0, message="Game started"
)
return room.slug