Skip to content

Commit

Permalink
Merge pull request #53 from HE-Arc/dev
Browse files Browse the repository at this point in the history
Merge dev -> main for final release
  • Loading branch information
joflucki authored May 2, 2024
2 parents d3ad9e6 + 36b371b commit bca46b1
Show file tree
Hide file tree
Showing 33 changed files with 1,509 additions and 230 deletions.
23 changes: 16 additions & 7 deletions api/arconnectmanager/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
"""


import environ
import os


from pathlib import Path
import environ
Expand All @@ -33,19 +30,16 @@
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/




# Take environment variables from .env file
environ.Env.read_env(os.path.join(BASE_DIR, '.env'))


# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG')

ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS') #TODO


# Application definition
Expand All @@ -64,8 +58,14 @@
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"django.contrib.sites",
"arconnectmanagerapp",
"rest_framework",
"rest_framework.authtoken",
"allauth",
"allauth.account",
"dj_rest_auth",
"dj_rest_auth.registration",
"corsheaders",
]

Expand All @@ -78,6 +78,7 @@
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'allauth.account.middleware.AccountMiddleware',
]

ROOT_URLCONF = 'arconnectmanager.urls'
Expand Down Expand Up @@ -166,3 +167,11 @@
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

SITE_ID = 1

REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.TokenAuthentication",
]
}
84 changes: 84 additions & 0 deletions api/arconnectmanagerapp/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import challonge
import environ
import random
import re
from datetime import datetime


class ChallongeAPI():
def __init__(self):
env = environ.Env()
CHALLONGE_API_USERNAME = env('CHALLONGE_API_USERNAME')
CHALLONGE_API_KEY = env('CHALLONGE_API_KEY')
self.match_desired_attr = ['id', 'round', 'scores_csv', 'state', 'player1_id', 'player2_id', 'winner_id']

challonge.set_credentials(CHALLONGE_API_USERNAME, CHALLONGE_API_KEY)

def create_tournament(self, name : str, participants : list):
unique_url = re.sub(r'[^a-zA-Z0-9_]', '', name) + "_" + str(random.randint(0, 1000)) #Generate an unique URL for the tournament (only letters, numbers and _ are allowed)
tournament = challonge.tournaments.create(name, unique_url, private=True)

for participant in participants:
challonge.participants.create(tournament['id'], participant)

challonge.tournaments.start(tournament['id'])
print(tournament['id'])
return {"id": tournament['id'], "image_url": tournament['live_image_url']}

def finalize_tournament(self, tournamentID : str):
return challonge.tournaments.finalize(tournamentID)

def get_matches(self, tournamentID: str):
filtered_matches = []

matches = challonge.matches.index(tournamentID)
participants = challonge.participants.index(tournamentID)

for match in matches:
filtered_matches.append(self.__get_match_filtered_info(match, participants))

return filtered_matches

def match_update_score(self, tournamentID : str, matchID : str, p1_ID : str, score_p1 : int, p2_ID : str, score_p2 : int):
final_score = str(score_p1) + "-" + str(score_p2)

winner_id = p1_ID
if score_p2 > score_p1:
winner_id = p2_ID

challonge.matches.update(tournamentID, matchID, scores_csv=final_score, winner_id=winner_id)
updated_match = challonge.matches.show(tournamentID, matchID)
return self.__get_match_filtered_info(updated_match, challonge.participants.index(tournamentID))

def is_matchID_valid(self, tournamentID : str, matchID : str):
matches = challonge.matches.index(tournamentID)
for match in matches:
if str(match['id']) == matchID:
print("Match found")
return True
return False

def are_matches_finished(self, tournamentID : str):
matches = challonge.matches.index(tournamentID)
for match in matches:
if match['state'] != 'complete':
return False
return True

def are_players_in_match(self, tournamentID : str, matchID : str, players_ID : list):
match = challonge.matches.show(tournamentID, matchID)
return str(match['player1_id']) in players_ID and str(match['player2_id']) in players_ID

#Tools functions

def __get_match_filtered_info(self, match, participants):
filtered_match = {attr: match[attr] for attr in self.match_desired_attr if attr in match}
filtered_match['player1_name'] = self.__get_participant_name_from_ID(participants, match['player1_id'])
filtered_match['player2_name'] = self.__get_participant_name_from_ID(participants, match['player2_id'])
return filtered_match

def __get_participant_name_from_ID(self, participants, id):
for participant in participants:
if participant["id"] == id:
return participant["name"]
return "Unknown"
22 changes: 22 additions & 0 deletions api/arconnectmanagerapp/migrations/0003_tournamentitem_players.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 5.0.1 on 2024-04-16 17:22

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("arconnectmanagerapp", "0002_alter_tournamentitem_state"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.AddField(
model_name="tournamentitem",
name="players",
field=models.ManyToManyField(
related_name="players", to=settings.AUTH_USER_MODEL
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.0.1 on 2024-04-27 14:28

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("arconnectmanagerapp", "0003_tournamentitem_players"),
]

operations = [
migrations.AddField(
model_name="tournamentitem",
name="challonge_id",
field=models.CharField(blank=True, max_length=100),
),
migrations.AddField(
model_name="tournamentitem",
name="image_url",
field=models.URLField(blank=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 5.0.1 on 2024-04-27 18:35

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
(
"arconnectmanagerapp",
"0004_tournamentitem_challonge_id_tournamentitem_image_url",
),
]

operations = [
migrations.RenameField(
model_name="tournamentitem",
old_name="image_url",
new_name="challonge_image_url",
),
]
11 changes: 8 additions & 3 deletions api/arconnectmanagerapp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@

#Tournament model
class TournamentItem(models.Model):
name = models.CharField(max_length=100) #Name of the tournament
description = models.TextField() #Description of the tournament
state = models.IntegerField( #State of the tournament : 0=closed, 1=open, 2=started 3=finished
name = models.CharField(max_length=100) #Name of the tournament
description = models.TextField() #Description of the tournament
state = models.IntegerField( #State of the tournament : 0=closed, 1=open, 2=started 3=finished
default=0,
validators=[MinValueValidator(0), MaxValueValidator(3)]
)
players = models.ManyToManyField(User, related_name='players')

challonge_id = models.CharField(max_length=100, blank=True) #ID of the tournament on Challonge
challonge_image_url = models.URLField(blank=True) #URL of the image of the tournament

created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
13 changes: 13 additions & 0 deletions api/arconnectmanagerapp/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from rest_framework import permissions

class TournamentPermission(permissions.BasePermission):
'''Permissions for the TournamentItem model'''
def has_permission(self, request, view):
if view.action in ['list', 'retrieve']:
return True
elif view.action in ['register', 'unregister']:
return request.user.is_authenticated
elif view.action in ['create', 'update', 'partial_update', 'destroy', 'open_registration', 'api_start', 'api_finish', 'api_get_matches', 'api_submit_scores']:
return request.user.is_authenticated and request.user.is_staff
else:
return False
21 changes: 16 additions & 5 deletions api/arconnectmanagerapp/serializers.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
from rest_framework import serializers
from django.core.validators import MinValueValidator
from django.contrib.auth.models import User
from .models import TournamentItem

class TournamentItemSerializer(serializers.HyperlinkedModelSerializer):
class TournamentItemSerializer(serializers.ModelSerializer):
''' Serializer for the TournamentItem model '''
class Meta:
model = TournamentItem
fields = [
'url',
'id',
'name',
'description',
'state'
'name',
'description',
'state',
'challonge_image_url',
'players',
]

read_only_fields = ['url', 'id', 'state', 'challonge_image_url', 'players']

class ScoreSerializer(serializers.Serializer):
''' Serializer for the score submission '''
match_id = serializers.CharField()
player1_id = serializers.CharField()
player2_id = serializers.CharField()
score_p1 = serializers.IntegerField(validators=[MinValueValidator(0)])
score_p2 = serializers.IntegerField(validators=[MinValueValidator(0)])
12 changes: 11 additions & 1 deletion api/arconnectmanagerapp/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
from django.urls import path, include
from . import views
from rest_framework.routers import DefaultRouter
from rest_framework.authtoken.views import obtain_auth_token
from dj_rest_auth.registration.views import RegisterView
from dj_rest_auth.views import LoginView, LogoutView

router = DefaultRouter()
router.register(r'tournaments', views.TournamentItemViewSet, basename='tournamentitem')

urlpatterns = [
path("", include(router.urls))
path("", include(router.urls)),


#User registration, login, logout and details
path("user/register/", RegisterView.as_view(), name="register"), #POST
path("user/login/", LoginView.as_view(), name="login"), #POST
path("user/logout/", LogoutView.as_view(), name="logout"), #POST
path('user/', views.UserView.as_view(), name='user_details'), #GET
]
Loading

0 comments on commit bca46b1

Please sign in to comment.