mirror of
https://github.com/evgen-app/chess_rpg_backend.git
synced 2024-11-25 11:04:03 +03:00
added game state base logic, minor changes
This commit is contained in:
parent
df3685b8fe
commit
73db40a4f7
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)]))
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user