Skip to content

Commit

Permalink
Merge pull request #29 from zakarm/production
Browse files Browse the repository at this point in the history
Production
  • Loading branch information
zakarm committed Jun 5, 2024
2 parents 502c938 + d65fde6 commit 2af1edd
Show file tree
Hide file tree
Showing 37 changed files with 905 additions and 208 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ POSTGRES_DB=db_member
POSTGRES_USER=zmrabet
POSTGRES_PASSWORD=zmrabet1337
POSTGRES_PORT=5432
DJANGO_SUPERUSER_USERNAME=apollo
DJANGO_SUPERUSER_EMAIL=zakariaemrabet48@gmail.com
DJANGO_SUPERUSER_PASSWORD=admin
DJANGO_SETTINGS_MODULE=ft_transcendence.settings
Expand Down
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
3 changes: 3 additions & 0 deletions app/back-end/compu_ai/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
6 changes: 6 additions & 0 deletions app/back-end/compu_ai/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class CompuAiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'compu_ai'
Empty file.
Binary file not shown.
3 changes: 3 additions & 0 deletions app/back-end/compu_ai/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.db import models

# Create your models here.
121 changes: 121 additions & 0 deletions app/back-end/compu_ai/serializer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
from rest_framework import serializers
from authentication.models import User
from game.models import Match, UserAchievements, Achievements
from django.db.models import Count, F, Q, Avg
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
from datetime import datetime
import numpy as np
import pandas as pd
from prophet import Prophet
import sys
from django.utils import timezone
import random
from datetime import timedelta

class AchievementSerializer(serializers.ModelSerializer):
class Meta:
model = Achievements
fields = '__all__'

class StatisticsSerializer(serializers.ModelSerializer):
top_player = serializers.SerializerMethodField()
avg_score = serializers.SerializerMethodField()
last_achiev = serializers.SerializerMethodField()
future_predictions = serializers.SerializerMethodField()
class Meta:
model = User
fields = ('id', 'username', 'top_player', 'avg_score', 'last_achiev', 'future_predictions')

def get_top_player(self, obj):
users_with_wins = User.objects.annotate(
wins_as_user_one=Count('match_user_one_set', filter=Q(match_user_one_set__score_user_one__gt=F('match_user_one_set__score_user_two'))),
wins_as_user_two=Count('match_user_two_set', filter=Q(match_user_two_set__score_user_two__gt=F('match_user_two_set__score_user_one')))
).annotate(total_wins=F('wins_as_user_one') + F('wins_as_user_two'))

most_wins_user = users_with_wins.order_by('-total_wins').first().username
return most_wins_user

def get_avg_score(self, obj):
user = User.objects.annotate(
avg_score_as_user_one=Avg('match_user_one_set__score_user_one'),
avg_score_as_user_two=Avg('match_user_two_set__score_user_two')
).filter(id=obj.id).first()
if user.avg_score_as_user_one is not None and user.avg_score_as_user_two is not None:
return (user.avg_score_as_user_one + user.avg_score_as_user_two ) / 2
elif user.avg_score_as_user_one is None:
return user.avg_score_as_user_two
elif user.avg_score_as_user_two is None:
return user.avg_score_as_user_one

def get_last_achiev(self, obj):
last_achievement = UserAchievements.objects.filter(user_id=obj.id).order_by('-achive_date').first()
print(last_achievement.achievement_id, file=sys.stderr)
if last_achievement:
return AchievementSerializer(instance=Achievements.objects.get(achievement_id=last_achievement.achievement_id)).data
else :
return None



def get_future_predictions(self, obj):
for _ in range(100):
# Generate a random start date from now to 6 months in the past
match_start = timezone.now() - timedelta(days=random.randint(0, 30*6))
match_end = match_start + timedelta(hours=random.randint(1, 3))
user_one_score = random.randint(0, 7)
user_two_score = random.randint(0, 7) if user_one_score < 7 else 7
match = Match.objects.create(
user_one_id=1, # Replace with the actual user ID
user_two_id=2, # Replace with the actual user ID
score_user_one=user_one_score,
score_user_two=user_two_score,
match_start=match_start.strftime("%Y-%m-%d %H:%M:%S"),
match_end=match_end.strftime("%Y-%m-%d %H:%M:%S"),
tackle_user_one=random.randint(0, 10),
tackle_user_two=random.randint(0, 10)
)
match.save()
# Filter matches for the specified user
user_matches = Match.objects.filter(Q(user_one=obj) | Q(user_two=obj))

if user_matches.exists():
# Prepare the data for Prophet
data = []
for match in user_matches:
if match.user_one == obj:
data.append({'ds': match.match_start, 'y': match.score_user_one})
else:
data.append({'ds': match.match_start, 'y': match.score_user_two})

df = pd.DataFrame(data)

# Ensure the 'ds' column is in datetime format and remove timezone
df['ds'] = pd.to_datetime(df['ds']).dt.tz_localize(None)

print(df, file = sys.stderr)
# Initialize and fit the model
model = Prophet()
model.fit(df)

# Create a dataframe with future dates
future_dates = pd.DataFrame({
'ds': pd.to_datetime(['2024-06-13', '2024-06-14'])
})

# Make predictions
forecast = model.predict(future_dates)

# Clamp the predictions to be within the range [0, 7]
future_predictions_with_dates = [
{
"date": row['ds'].strftime('%Y-%m-%d'),
"predicted_score": row['yhat']
}
for _, row in forecast.iterrows()
]

return future_predictions_with_dates

return None
3 changes: 3 additions & 0 deletions app/back-end/compu_ai/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
6 changes: 6 additions & 0 deletions app/back-end/compu_ai/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.urls import path
from .views import (StatisticsView)

urlpatterns = [
path('statistics', StatisticsView.as_view(), name='statistics'),
]
Empty file added app/back-end/compu_ai/utils.py
Empty file.
16 changes: 16 additions & 0 deletions app/back-end/compu_ai/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django.shortcuts import render
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from .serializer import StatisticsSerializer
from rest_framework.response import Response

# Create your views here.
class StatisticsView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]

def get(self, request):
user = request.user
serializer = StatisticsSerializer(instance=user)
return Response(serializer.data)
2 changes: 1 addition & 1 deletion app/back-end/dashboards/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class FriendshipSerializer(serializers.ModelSerializer):
blocked = serializers.SerializerMethodField()
class Meta:
model = Friendship
fields = ('user', 'is_accepted', 'blocked', 'is_user_from')
fields = ('user', 'freindship_id', 'is_accepted', 'blocked', 'is_user_from')

def get_user(self, obj):
if obj.user_from.id == self.context['id']:
Expand Down
1 change: 1 addition & 0 deletions app/back-end/ft_transcendence/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
'django.contrib.auth',
'django.contrib.contenttypes',
'game.apps.GameConfig',
'compu_ai.apps.CompuAiConfig',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
Expand Down
25 changes: 6 additions & 19 deletions app/back-end/ft_transcendence/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,21 @@
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include, re_path
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.urls import path, include
from rest_framework_simplejwt.views import (TokenObtainPairView,
TokenRefreshView,
TokenVerifyView)
from rest_framework import permissions
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView

# schema_view = get_schema_view(
# openapi.Info(
# title="ft_transcendence",
# default_version='v1',
# description="API documentation",
# terms_of_service="https://www.google.com/policies/terms/",
# contact=openapi.Contact(email="zmrabet@student.1337.ma"),
# license=openapi.License(name="BSD License"),
# ),
# public=True,
# permission_classes=(permissions.AllowAny,),
# authentication_classes=[JWTAuthentication],
# # default_security=[{'Bearer': []}],
# )
from drf_spectacular.views import (SpectacularAPIView,
SpectacularRedocView,
SpectacularSwaggerView)

urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('authentication.urls')),
path('api/', include('dashboards.urls')),
path('api/', include('game.urls')),
path('api/', include('game.urls')),
path('api/', include('compu_ai.urls')),
path('api/token', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/refresh', TokenRefreshView.as_view(), name='token_refresh'),
path('api/verify', TokenVerifyView.as_view(), name='token_verify'),
Expand Down
6 changes: 4 additions & 2 deletions app/back-end/game/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
Tournaments,
Tournamentsmatches,
Achievements,
UserAchievements)
UserAchievements,
GameTable)

class UserAdmin(admin.ModelAdmin):
"Class for user display in admin page"
Expand All @@ -18,4 +19,5 @@ class UserAdmin(admin.ModelAdmin):
admin.site.register(Tournamentsmatches)
admin.site.register(Tournaments)
admin.site.register(Achievements)
admin.site.register(UserAchievements)
admin.site.register(UserAchievements)
admin.site.register(GameTable)
9 changes: 8 additions & 1 deletion app/back-end/game/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ class Match(models.Model):
class Meta:
db_table = 'Matches'

def get_winner(self):
if self.score_user_one > self.score_user_two:
return self.user_one
elif self.score_user_two > self.score_user_one:
return self.user_two
return None

class Tournaments(models.Model):
tournament_id = models.AutoField(primary_key=True)
tournament_name = models.CharField(max_length=30, unique=True)
Expand Down Expand Up @@ -58,6 +65,6 @@ class GameTable(models.Model):
table_color = models.CharField(max_length=10, blank=True)
ball_color = models.CharField(max_length=10, blank=True)
paddle_color = models.CharField(max_length=10, blank=True)
ball_color = models.IntegerField(blank=True)
game_difficulty = models.IntegerField()
class Meta:
db_table= 'GameTable'
56 changes: 55 additions & 1 deletion app/back-end/game/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
Tournamentsmatches,
Match,
Achievements,
GameTable,
UserAchievements
)
from authentication.models import User
import sys

class TournamentsmatchesSerializer(serializers.ModelSerializer):
match = MatchSerializer()
Expand Down Expand Up @@ -133,4 +135,56 @@ def get_match(self, obj):
return self.get_achievement(obj, 'match', ['speedy', 'last', 'king'])

def get_ai(self, obj):
return self.get_achievement(obj, 'ai', ['challenger', 'rivalry', 'legend'])
return self.get_achievement(obj, 'ai', ['challenger', 'rivalry', 'legend'])

class GameTableSerializer(serializers.ModelSerializer):
class Meta:
model = GameTable
fields = '__all__'

class GameSettingsSerializer(serializers.ModelSerializer):
country = serializers.SerializerMethodField()
city = serializers.SerializerMethodField()
game_table = serializers.SerializerMethodField()
new_password = serializers.CharField(write_only=True, required=False)
class Meta:
model = User
fields = ('first_name', 'last_name', 'username', 'image_url', 'is_2fa_enabled', 'two_fa_secret_key',
'email', 'country', 'city', 'game_table', 'new_password')

def validate_email(self, value):
user = self.instance
if User.objects.filter(email=value).exclude(id=user.id).exists():
raise serializers.ValidationError("User with this email already exists.")
return value

def get_city(self, obj):
if obj.location:
if '/' in obj.location:
return obj.location.split('/')[1]
else :
return "NaN"
else: return "NaN"

def get_country(self, obj):
if obj.location:
if '/' in obj.location:
return obj.location.split('/')[0]
else :
return obj.location
else: return "NaN"

def get_game_table(self, obj):
game_table = GameTable.objects.filter(user=obj).first()
if game_table:
return GameTableSerializer(instance=game_table).data
else:
return None

def to_representation(self, instance):
representation = super().to_representation(instance)
game_table_representation = representation.pop('game_table', {})
if game_table_representation:
for key, value in game_table_representation.items():
representation[key] = value
return representation
4 changes: 3 additions & 1 deletion app/back-end/game/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from django.urls import path
from .views import (TournamentsDataView,
AchievementsDataViews,
CreateTournament)
CreateTournament,
GameSettingsView)

urlpatterns = [
path('tournaments', TournamentsDataView.as_view(), name='tournaments'),
path('achievements', AchievementsDataViews.as_view(), name='achievements'),
path('create-tournament', CreateTournament.as_view(), name='create-tournament'),
path('game-settings', GameSettingsView.as_view(), name='game-settings'),
]
Loading

0 comments on commit 2af1edd

Please sign in to comment.